all: rewrite tests to use testify instead of goconvey (#300)

This commit is contained in:
Márk Sági-Kazár
2021-09-16 00:03:44 +08:00
committed by GitHub
parent 326d24fbbe
commit bba62c3754
8 changed files with 1530 additions and 1473 deletions
+179 -201
View File
@@ -20,53 +20,51 @@ import (
"runtime"
"testing"
. "github.com/smartystreets/goconvey/convey"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/ini.v1"
)
func TestEmpty(t *testing.T) {
Convey("Create an empty object", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
f := ini.Empty()
require.NotNil(t, f)
// Should only have the default section
So(len(f.Sections()), ShouldEqual, 1)
// Should only have the default section
assert.Len(t, f.Sections(), 1)
// Default section should not contain any key
So(len(f.Section("").Keys()), ShouldBeZeroValue)
})
// Default section should not contain any key
assert.Len(t, f.Section("").Keys(), 0)
}
func TestFile_NewSection(t *testing.T) {
Convey("Create a new section", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
f := ini.Empty()
require.NotNil(t, f)
sec, err := f.NewSection("author")
require.NoError(t, err)
require.NotNil(t, sec)
assert.Equal(t, "author", sec.Name())
assert.Equal(t, []string{ini.DefaultSection, "author"}, f.SectionStrings())
t.Run("with duplicated name", func(t *testing.T) {
sec, err := f.NewSection("author")
So(err, ShouldBeNil)
So(sec, ShouldNotBeNil)
So(sec.Name(), ShouldEqual, "author")
require.NoError(t, err)
require.NotNil(t, sec)
So(f.SectionStrings(), ShouldResemble, []string{ini.DefaultSection, "author"})
// Does nothing if section already exists
assert.Equal(t, []string{ini.DefaultSection, "author"}, f.SectionStrings())
})
Convey("With duplicated name", func() {
sec, err := f.NewSection("author")
So(err, ShouldBeNil)
So(sec, ShouldNotBeNil)
// Does nothing if section already exists
So(f.SectionStrings(), ShouldResemble, []string{ini.DefaultSection, "author"})
})
Convey("With empty string", func() {
_, err := f.NewSection("")
So(err, ShouldNotBeNil)
})
t.Run("with empty string", func(t *testing.T) {
_, err := f.NewSection("")
require.Error(t, err)
})
}
func TestFile_NonUniqueSection(t *testing.T) {
Convey("Read and write non-unique sections", t, func() {
t.Run("read and write non-unique sections", func(t *testing.T) {
f, err := ini.LoadSources(ini.LoadOptions{
AllowNonUniqueSections: true,
}, []byte(`[Interface]
@@ -81,21 +79,21 @@ AllowedIPs = 192.168.2.2/32
[Peer]
PublicKey = <client2's publickey>
AllowedIPs = 192.168.2.3/32`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
sec, err := f.NewSection("Peer")
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
_, _ = sec.NewKey("PublicKey", "<client3's publickey>")
_, _ = sec.NewKey("AllowedIPs", "192.168.2.4/32")
var buf bytes.Buffer
_, err = f.WriteTo(&buf)
So(err, ShouldBeNil)
require.NoError(t, err)
str := buf.String()
So(str, ShouldEqual, `[Interface]
assert.Equal(t, `[Interface]
Address = 192.168.2.1
PrivateKey = <server's privatekey>
ListenPort = 51820
@@ -112,10 +110,10 @@ AllowedIPs = 192.168.2.3/32
PublicKey = <client3's publickey>
AllowedIPs = 192.168.2.4/32
`)
`, str)
})
Convey("Delete non-unique section", t, func() {
t.Run("delete non-unique section", func(t *testing.T) {
f, err := ini.LoadSources(ini.LoadOptions{
AllowNonUniqueSections: true,
}, []byte(`[Interface]
@@ -136,17 +134,17 @@ PublicKey = <client3's publickey>
AllowedIPs = 192.168.2.4/32
`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
err = f.DeleteSectionWithIndex("Peer", 1)
So(err, ShouldBeNil)
require.NoError(t, err)
var buf bytes.Buffer
_, err = f.WriteTo(&buf)
So(err, ShouldBeNil)
require.NoError(t, err)
str := buf.String()
So(str, ShouldEqual, `[Interface]
assert.Equal(t, `[Interface]
Address = 192.168.2.1
PrivateKey = <server's privatekey>
ListenPort = 51820
@@ -159,223 +157,209 @@ AllowedIPs = 192.168.2.2/32
PublicKey = <client3's publickey>
AllowedIPs = 192.168.2.4/32
`)
`, str)
})
Convey("Delete all sections", t, func() {
t.Run("delete all sections", func(t *testing.T) {
f := ini.Empty(ini.LoadOptions{
AllowNonUniqueSections: true,
})
So(f, ShouldNotBeNil)
require.NotNil(t, f)
_ = f.NewSections("Interface", "Peer", "Peer")
So(f.SectionStrings(), ShouldResemble, []string{ini.DefaultSection, "Interface", "Peer", "Peer"})
assert.Equal(t, []string{ini.DefaultSection, "Interface", "Peer", "Peer"}, f.SectionStrings())
f.DeleteSection("Peer")
So(f.SectionStrings(), ShouldResemble, []string{ini.DefaultSection, "Interface"})
assert.Equal(t, []string{ini.DefaultSection, "Interface"}, f.SectionStrings())
})
}
func TestFile_NewRawSection(t *testing.T) {
Convey("Create a new raw section", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
f := ini.Empty()
require.NotNil(t, f)
sec, err := f.NewRawSection("comments", `1111111111111111111000000000000000001110000
sec, err := f.NewRawSection("comments", `1111111111111111111000000000000000001110000
111111111111111111100000000000111000000000`)
So(err, ShouldBeNil)
So(sec, ShouldNotBeNil)
So(sec.Name(), ShouldEqual, "comments")
require.NoError(t, err)
require.NotNil(t, sec)
assert.Equal(t, "comments", sec.Name())
So(f.SectionStrings(), ShouldResemble, []string{ini.DefaultSection, "comments"})
So(f.Section("comments").Body(), ShouldEqual, `1111111111111111111000000000000000001110000
111111111111111111100000000000111000000000`)
assert.Equal(t, []string{ini.DefaultSection, "comments"}, f.SectionStrings())
assert.Equal(t, `1111111111111111111000000000000000001110000
111111111111111111100000000000111000000000`, f.Section("comments").Body())
Convey("With duplicated name", func() {
sec, err := f.NewRawSection("comments", `1111111111111111111000000000000000001110000`)
So(err, ShouldBeNil)
So(sec, ShouldNotBeNil)
So(f.SectionStrings(), ShouldResemble, []string{ini.DefaultSection, "comments"})
t.Run("with duplicated name", func(t *testing.T) {
sec, err := f.NewRawSection("comments", `1111111111111111111000000000000000001110000`)
require.NoError(t, err)
require.NotNil(t, sec)
assert.Equal(t, []string{ini.DefaultSection, "comments"}, f.SectionStrings())
// Overwrite previous existed section
So(f.Section("comments").Body(), ShouldEqual, `1111111111111111111000000000000000001110000`)
})
// Overwrite previous existed section
assert.Equal(t, `1111111111111111111000000000000000001110000`, f.Section("comments").Body())
})
Convey("With empty string", func() {
_, err := f.NewRawSection("", "")
So(err, ShouldNotBeNil)
})
t.Run("with empty string", func(t *testing.T) {
_, err := f.NewRawSection("", "")
require.Error(t, err)
})
}
func TestFile_NewSections(t *testing.T) {
Convey("Create new sections", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
f := ini.Empty()
require.NotNil(t, f)
So(f.NewSections("package", "author"), ShouldBeNil)
So(f.SectionStrings(), ShouldResemble, []string{ini.DefaultSection, "package", "author"})
assert.NoError(t, f.NewSections("package", "author"))
assert.Equal(t, []string{ini.DefaultSection, "package", "author"}, f.SectionStrings())
Convey("With duplicated name", func() {
So(f.NewSections("author", "features"), ShouldBeNil)
t.Run("with duplicated name", func(t *testing.T) {
assert.NoError(t, f.NewSections("author", "features"))
// Ignore section already exists
So(f.SectionStrings(), ShouldResemble, []string{ini.DefaultSection, "package", "author", "features"})
})
// Ignore section already exists
assert.Equal(t, []string{ini.DefaultSection, "package", "author", "features"}, f.SectionStrings())
})
Convey("With empty string", func() {
So(f.NewSections("", ""), ShouldNotBeNil)
})
t.Run("with empty string", func(t *testing.T) {
assert.Error(t, f.NewSections("", ""))
})
}
func TestFile_GetSection(t *testing.T) {
Convey("Get a section", t, func() {
f, err := ini.Load(fullConf)
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
f, err := ini.Load(fullConf)
require.NoError(t, err)
require.NotNil(t, f)
sec, err := f.GetSection("author")
So(err, ShouldBeNil)
So(sec, ShouldNotBeNil)
So(sec.Name(), ShouldEqual, "author")
sec, err := f.GetSection("author")
require.NoError(t, err)
require.NotNil(t, sec)
assert.Equal(t, "author", sec.Name())
Convey("Section not exists", func() {
_, err := f.GetSection("404")
So(err, ShouldNotBeNil)
})
t.Run("section not exists", func(t *testing.T) {
_, err := f.GetSection("404")
require.Error(t, err)
})
}
func TestFile_Section(t *testing.T) {
Convey("Get a section", t, func() {
t.Run("get a section", func(t *testing.T) {
f, err := ini.Load(fullConf)
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
sec := f.Section("author")
So(sec, ShouldNotBeNil)
So(sec.Name(), ShouldEqual, "author")
require.NotNil(t, sec)
assert.Equal(t, "author", sec.Name())
Convey("Section not exists", func() {
t.Run("section not exists", func(t *testing.T) {
sec := f.Section("404")
So(sec, ShouldNotBeNil)
So(sec.Name(), ShouldEqual, "404")
require.NotNil(t, sec)
assert.Equal(t, "404", sec.Name())
})
})
Convey("Get default section in lower case with insensitive load", t, func() {
t.Run("get default section in lower case with insensitive load", func(t *testing.T) {
f, err := ini.InsensitiveLoad([]byte(`
[default]
NAME = ini
VERSION = v1`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
So(f.Section("").Key("name").String(), ShouldEqual, "ini")
So(f.Section("").Key("version").String(), ShouldEqual, "v1")
assert.Equal(t, "ini", f.Section("").Key("name").String())
assert.Equal(t, "v1", f.Section("").Key("version").String())
})
}
func TestFile_Sections(t *testing.T) {
Convey("Get all sections", t, func() {
f, err := ini.Load(fullConf)
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
f, err := ini.Load(fullConf)
require.NoError(t, err)
require.NotNil(t, f)
secs := f.Sections()
names := []string{ini.DefaultSection, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "string escapes", "advance"}
So(len(secs), ShouldEqual, len(names))
for i, name := range names {
So(secs[i].Name(), ShouldEqual, name)
}
})
secs := f.Sections()
names := []string{ini.DefaultSection, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "string escapes", "advance"}
assert.Len(t, secs, len(names))
for i, name := range names {
assert.Equal(t, name, secs[i].Name())
}
}
func TestFile_ChildSections(t *testing.T) {
Convey("Get child sections by parent name", t, func() {
f, err := ini.Load([]byte(`
f, err := ini.Load([]byte(`
[node]
[node.biz1]
[node.biz2]
[node.biz3]
[node.bizN]
`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
children := f.ChildSections("node")
names := []string{"node.biz1", "node.biz2", "node.biz3", "node.bizN"}
So(len(children), ShouldEqual, len(names))
for i, name := range names {
So(children[i].Name(), ShouldEqual, name)
}
})
children := f.ChildSections("node")
names := []string{"node.biz1", "node.biz2", "node.biz3", "node.bizN"}
assert.Len(t, children, len(names))
for i, name := range names {
assert.Equal(t, name, children[i].Name())
}
}
func TestFile_SectionStrings(t *testing.T) {
Convey("Get all section names", t, func() {
f, err := ini.Load(fullConf)
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
f, err := ini.Load(fullConf)
require.NoError(t, err)
require.NotNil(t, f)
So(f.SectionStrings(), ShouldResemble, []string{ini.DefaultSection, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "string escapes", "advance"})
})
assert.Equal(t, []string{ini.DefaultSection, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "string escapes", "advance"}, f.SectionStrings())
}
func TestFile_DeleteSection(t *testing.T) {
Convey("Delete a section", t, func() {
t.Run("delete a section", func(t *testing.T) {
f := ini.Empty()
So(f, ShouldNotBeNil)
require.NotNil(t, f)
_ = f.NewSections("author", "package", "features")
f.DeleteSection("features")
f.DeleteSection("")
So(f.SectionStrings(), ShouldResemble, []string{"author", "package"})
assert.Equal(t, []string{"author", "package"}, f.SectionStrings())
})
Convey("Delete default section", t, func() {
t.Run("delete default section", func(t *testing.T) {
f := ini.Empty()
So(f, ShouldNotBeNil)
require.NotNil(t, f)
f.Section("").Key("foo").SetValue("bar")
f.Section("section1").Key("key1").SetValue("value1")
f.DeleteSection("")
So(f.SectionStrings(), ShouldResemble, []string{"section1"})
assert.Equal(t, []string{"section1"}, f.SectionStrings())
var buf bytes.Buffer
_, err := f.WriteTo(&buf)
So(err, ShouldBeNil)
require.NoError(t, err)
So(buf.String(), ShouldEqual, `[section1]
assert.Equal(t, `[section1]
key1 = value1
`)
`, buf.String())
})
Convey("Delete a section with InsensitiveSections", t, func() {
t.Run("delete a section with InsensitiveSections", func(t *testing.T) {
f := ini.Empty(ini.LoadOptions{InsensitiveSections: true})
So(f, ShouldNotBeNil)
require.NotNil(t, f)
_ = f.NewSections("author", "package", "features")
f.DeleteSection("FEATURES")
f.DeleteSection("")
So(f.SectionStrings(), ShouldResemble, []string{"author", "package"})
assert.Equal(t, []string{"author", "package"}, f.SectionStrings())
})
}
func TestFile_Append(t *testing.T) {
Convey("Append a data source", t, func() {
f := ini.Empty()
So(f, ShouldNotBeNil)
f := ini.Empty()
require.NotNil(t, f)
So(f.Append(minimalConf, []byte(`
assert.NoError(t, f.Append(minimalConf, []byte(`
[author]
NAME = Unknwon`)), ShouldBeNil)
NAME = Unknwon`)))
Convey("With bad input", func() {
So(f.Append(123), ShouldNotBeNil)
So(f.Append(minimalConf, 123), ShouldNotBeNil)
})
t.Run("with bad input", func(t *testing.T) {
assert.Error(t, f.Append(123))
assert.Error(t, f.Append(minimalConf, 123))
})
}
@@ -384,10 +368,10 @@ func TestFile_WriteTo(t *testing.T) {
t.Skip("Skipping testing on Windows")
}
Convey("Write content to somewhere", t, func() {
t.Run("write content to somewhere", func(t *testing.T) {
f, err := ini.Load(fullConf)
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
f.Section("author").Comment = `Information about package author
# Bio can be written in multiple lines.`
@@ -397,19 +381,19 @@ func TestFile_WriteTo(t *testing.T) {
var buf bytes.Buffer
_, err = f.WriteTo(&buf)
So(err, ShouldBeNil)
require.NoError(t, err)
golden := "testdata/TestFile_WriteTo.golden"
if *update {
So(ioutil.WriteFile(golden, buf.Bytes(), 0644), ShouldBeNil)
require.NoError(t, ioutil.WriteFile(golden, buf.Bytes(), 0644))
}
expected, err := ioutil.ReadFile(golden)
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, string(expected))
require.NoError(t, err)
assert.Equal(t, string(expected), buf.String())
})
Convey("Support multiline comments", t, func() {
t.Run("support multiline comments", func(t *testing.T) {
f, err := ini.Load([]byte(`
#
# general.domain
@@ -417,15 +401,15 @@ func TestFile_WriteTo(t *testing.T) {
# Domain name of XX system.
domain = mydomain.com
`))
So(err, ShouldBeNil)
require.NoError(t, err)
f.Section("").Key("test").Comment = "Multiline\nComment"
var buf bytes.Buffer
_, err = f.WriteTo(&buf)
So(err, ShouldBeNil)
require.NoError(t, err)
So(buf.String(), ShouldEqual, `#
assert.Equal(t, `#
# general.domain
#
# Domain name of XX system.
@@ -434,46 +418,43 @@ domain = mydomain.com
; Comment
test =
`)
`, buf.String())
})
Convey("Keep leading and trailing spaces in value", t, func() {
t.Run("keep leading and trailing spaces in value", func(t *testing.T) {
f, _ := ini.Load([]byte(`[foo]
bar1 = ' val ue1 '
bar2 = """ val ue2 """
bar3 = " val ue3 "
`))
So(f, ShouldNotBeNil)
require.NotNil(t, f)
var buf bytes.Buffer
_, err := f.WriteTo(&buf)
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, `[foo]
require.NoError(t, err)
assert.Equal(t, `[foo]
bar1 = " val ue1 "
bar2 = " val ue2 "
bar3 = " val ue3 "
`)
`, buf.String())
})
}
func TestFile_SaveTo(t *testing.T) {
Convey("Write content to somewhere", t, func() {
f, err := ini.Load(fullConf)
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
f, err := ini.Load(fullConf)
require.NoError(t, err)
require.NotNil(t, f)
So(f.SaveTo("testdata/conf_out.ini"), ShouldBeNil)
So(f.SaveToIndent("testdata/conf_out.ini", "\t"), ShouldBeNil)
})
assert.NoError(t, f.SaveTo("testdata/conf_out.ini"))
assert.NoError(t, f.SaveToIndent("testdata/conf_out.ini", "\t"))
}
func TestFile_WriteToWithOutputDelimiter(t *testing.T) {
Convey("Write content to somewhere using a custom output delimiter", t, func() {
f, err := ini.LoadSources(ini.LoadOptions{
KeyValueDelimiterOnWrite: "->",
}, []byte(`[Others]
f, err := ini.LoadSources(ini.LoadOptions{
KeyValueDelimiterOnWrite: "->",
}, []byte(`[Others]
Cities = HangZhou|Boston
Visits = 1993-10-07T20:17:05Z, 1993-10-07T20:17:05Z
Years = 1993,1994
@@ -483,11 +464,11 @@ Populations = 12345678,98765432
Coordinates = 192.168,10.11
Flags = true,false
Note = Hello world!`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
var actual bytes.Buffer
var expected = []byte(`[Others]
var actual bytes.Buffer
var expected = []byte(`[Others]
Cities -> HangZhou|Boston
Visits -> 1993-10-07T20:17:05Z, 1993-10-07T20:17:05Z
Years -> 1993,1994
@@ -499,28 +480,25 @@ Flags -> true,false
Note -> Hello world!
`)
_, err = f.WriteTo(&actual)
So(err, ShouldBeNil)
_, err = f.WriteTo(&actual)
require.NoError(t, err)
So(bytes.Equal(expected, actual.Bytes()), ShouldBeTrue)
})
assert.Equal(t, expected, actual.Bytes())
}
// Inspired by https://github.com/go-ini/ini/issues/207
func TestReloadAfterShadowLoad(t *testing.T) {
Convey("Reload file after ShadowLoad", t, func() {
f, err := ini.ShadowLoad([]byte(`
f, err := ini.ShadowLoad([]byte(`
[slice]
v = 1
v = 2
v = 3
`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
So(f.Section("slice").Key("v").ValueWithShadows(), ShouldResemble, []string{"1", "2", "3"})
assert.Equal(t, []string{"1", "2", "3"}, f.Section("slice").Key("v").ValueWithShadows())
So(f.Reload(), ShouldBeNil)
So(f.Section("slice").Key("v").ValueWithShadows(), ShouldResemble, []string{"1", "2", "3"})
})
require.NoError(t, f.Reload())
assert.Equal(t, []string{"1", "2", "3"}, f.Section("slice").Key("v").ValueWithShadows())
}
+5 -7
View File
@@ -17,13 +17,11 @@ package ini
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
"github.com/stretchr/testify/assert"
)
func Test_isSlice(t *testing.T) {
Convey("Check if a string is in the slice", t, func() {
ss := []string{"a", "b", "c"}
So(inSlice("a", ss), ShouldBeTrue)
So(inSlice("d", ss), ShouldBeFalse)
})
func TestIsInSlice(t *testing.T) {
ss := []string{"a", "b", "c"}
assert.True(t, inSlice("a", ss))
assert.False(t, inSlice("d", ss))
}
+22 -20
View File
@@ -5,7 +5,9 @@ import (
"runtime"
"testing"
. "github.com/smartystreets/goconvey/convey"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/ini.v1"
)
@@ -20,25 +22,24 @@ func TestMultiline(t *testing.T) {
t.Skip("Skipping testing on Windows")
}
Convey("Parse Python-style multiline values", t, func() {
path := filepath.Join("testdata", "multiline.ini")
f, err := ini.LoadSources(ini.LoadOptions{
AllowPythonMultilineValues: true,
ReaderBufferSize: 64 * 1024,
}, path)
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
So(len(f.Sections()), ShouldEqual, 1)
path := filepath.Join("testdata", "multiline.ini")
f, err := ini.LoadSources(ini.LoadOptions{
AllowPythonMultilineValues: true,
ReaderBufferSize: 64 * 1024,
}, path)
require.NoError(t, err)
require.NotNil(t, f)
assert.Len(t, f.Sections(), 1)
defaultSection := f.Section("")
So(f.Section(""), ShouldNotBeNil)
defaultSection := f.Section("")
assert.NotNil(t, f.Section(""))
var testData testData
err = defaultSection.MapTo(&testData)
So(err, ShouldBeNil)
So(testData.Value1, ShouldEqual, "some text here\nsome more text here\n\nthere is an empty line above and below\n")
So(testData.Value2, ShouldEqual, "there is an empty line above\nthat is not indented so it should not be part\nof the value")
So(testData.Value3, ShouldEqual, `.
var testData testData
err = defaultSection.MapTo(&testData)
require.NoError(t, err)
assert.Equal(t, "some text here\nsome more text here\n\nthere is an empty line above and below\n", testData.Value1)
assert.Equal(t, "there is an empty line above\nthat is not indented so it should not be part\nof the value", testData.Value2)
assert.Equal(t, `.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Eu consequat ac felis donec et odio pellentesque diam volutpat. Mauris commodo quis imperdiet massa tincidunt nunc. Interdum velit euismod in pellentesque. Nisl condimentum id venenatis a condimentum vitae sapien pellentesque. Nascetur ridiculus mus mauris vitae. Posuere urna nec tincidunt praesent semper feugiat. Lorem donec massa sapien faucibus et molestie ac feugiat sed. Ipsum dolor sit amet consectetur adipiscing elit. Enim sed faucibus turpis in eu mi. A diam sollicitudin tempor id. Quam nulla porttitor massa id neque aliquam vestibulum morbi blandit.
@@ -60,6 +61,7 @@ Malesuada fames ac turpis egestas. Suscipit tellus mauris a diam maecenas. Turpi
Id ornare arcu odio ut sem. Arcu dictum varius duis at consectetur lorem donec massa sapien. Proin libero nunc consequat interdum varius sit. Ut eu sem integer vitae justo. Vitae elementum curabitur vitae nunc. Diam quam nulla porttitor massa. Lectus mauris ultrices eros in cursus turpis massa tincidunt dui. Natoque penatibus et magnis dis parturient montes. Pellentesque habitant morbi tristique senectus et netus et malesuada fames. Libero nunc consequat interdum varius sit. Rhoncus dolor purus non enim praesent. Pellentesque sit amet porttitor eget. Nibh tortor id aliquet lectus proin nibh. Fermentum iaculis eu non diam phasellus vestibulum lorem sed.
Eu feugiat pretium nibh ipsum consequat nisl vel pretium lectus. Habitant morbi tristique senectus et netus et malesuada fames ac. Urna condimentum mattis pellentesque id. Lorem sed risus ultricies tristique nulla aliquet enim tortor at. Ipsum dolor sit amet consectetur adipiscing elit. Convallis a cras semper auctor neque vitae tempus quam. A diam sollicitudin tempor id eu nisl nunc mi ipsum. Maecenas sed enim ut sem viverra aliquet eget. Massa enim nec dui nunc mattis enim. Nam aliquam sem et tortor consequat. Adipiscing commodo elit at imperdiet dui accumsan sit amet nulla. Nullam eget felis eget nunc lobortis. Mauris a diam maecenas sed enim ut sem viverra. Ornare massa eget egestas purus. In hac habitasse platea dictumst. Ut tortor pretium viverra suspendisse potenti nullam ac tortor. Nisl nunc mi ipsum faucibus. At varius vel pharetra vel. Mauris ultrices eros in cursus turpis massa tincidunt.`)
})
Eu feugiat pretium nibh ipsum consequat nisl vel pretium lectus. Habitant morbi tristique senectus et netus et malesuada fames ac. Urna condimentum mattis pellentesque id. Lorem sed risus ultricies tristique nulla aliquet enim tortor at. Ipsum dolor sit amet consectetur adipiscing elit. Convallis a cras semper auctor neque vitae tempus quam. A diam sollicitudin tempor id eu nisl nunc mi ipsum. Maecenas sed enim ut sem viverra aliquet eget. Massa enim nec dui nunc mattis enim. Nam aliquam sem et tortor consequat. Adipiscing commodo elit at imperdiet dui accumsan sit amet nulla. Nullam eget felis eget nunc lobortis. Mauris a diam maecenas sed enim ut sem viverra. Ornare massa eget egestas purus. In hac habitasse platea dictumst. Ut tortor pretium viverra suspendisse potenti nullam ac tortor. Nisl nunc mi ipsum faucibus. At varius vel pharetra vel. Mauris ultrices eros in cursus turpis massa tincidunt.`,
testData.Value3,
)
}
+667 -627
View File
File diff suppressed because it is too large Load Diff
+291 -273
View File
@@ -22,525 +22,541 @@ import (
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/ini.v1"
)
func TestKey_AddShadow(t *testing.T) {
Convey("Add shadow to a key", t, func() {
t.Run("add shadow to a key", func(t *testing.T) {
f, err := ini.ShadowLoad([]byte(`
[notes]
-: note1`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
So(k.AddShadow("ini.v1"), ShouldBeNil)
So(k.ValueWithShadows(), ShouldResemble, []string{"ini", "ini.v1"})
assert.NoError(t, k.AddShadow("ini.v1"))
assert.Equal(t, []string{"ini", "ini.v1"}, k.ValueWithShadows())
Convey("Add shadow to boolean key", func() {
t.Run("add shadow to boolean key", func(t *testing.T) {
k, err := f.Section("").NewBooleanKey("published")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
So(k.AddShadow("beta"), ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
assert.Error(t, k.AddShadow("beta"))
})
Convey("Add shadow to auto-increment key", func() {
So(f.Section("notes").Key("#1").AddShadow("beta"), ShouldNotBeNil)
t.Run("add shadow to auto-increment key", func(t *testing.T) {
assert.Error(t, f.Section("notes").Key("#1").AddShadow("beta"))
})
Convey("Deduplicate an existing value", func() {
t.Run("deduplicate an existing value", func(t *testing.T) {
k := f.Section("").Key("NAME")
So(k.AddShadow("ini"), ShouldBeNil)
So(k.ValueWithShadows(), ShouldResemble, []string{"ini", "ini.v1"})
assert.NoError(t, k.AddShadow("ini"))
assert.Equal(t, []string{"ini", "ini.v1"}, k.ValueWithShadows())
})
})
Convey("Allow duplicate shadowed values", t, func() {
t.Run("allow duplicate shadowed values", func(t *testing.T) {
f := ini.Empty(ini.LoadOptions{
AllowShadows: true,
AllowDuplicateShadowValues: true,
})
So(f, ShouldNotBeNil)
require.NotNil(t, f)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
So(k.AddShadow("ini.v1"), ShouldBeNil)
So(k.AddShadow("ini"), ShouldBeNil)
So(k.AddShadow("ini"), ShouldBeNil)
So(k.ValueWithShadows(), ShouldResemble, []string{"ini", "ini.v1", "ini", "ini"})
assert.NoError(t, k.AddShadow("ini.v1"))
assert.NoError(t, k.AddShadow("ini"))
assert.NoError(t, k.AddShadow("ini"))
assert.Equal(t, []string{"ini", "ini.v1", "ini", "ini"}, k.ValueWithShadows())
})
Convey("Shadow is not allowed", t, func() {
t.Run("shadow is not allowed", func(t *testing.T) {
f := ini.Empty()
So(f, ShouldNotBeNil)
require.NotNil(t, f)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
So(k.AddShadow("ini.v1"), ShouldNotBeNil)
assert.Error(t, k.AddShadow("ini.v1"))
})
}
// Helpers for slice tests.
func float64sEqual(values []float64, expected ...float64) {
So(values, ShouldHaveLength, len(expected))
func float64sEqual(t *testing.T, values []float64, expected ...float64) {
t.Helper()
assert.Len(t, values, len(expected))
for i, v := range expected {
So(values[i], ShouldEqual, v)
assert.Equal(t, v, values[i])
}
}
func intsEqual(values []int, expected ...int) {
So(values, ShouldHaveLength, len(expected))
func intsEqual(t *testing.T, values []int, expected ...int) {
t.Helper()
assert.Len(t, values, len(expected))
for i, v := range expected {
So(values[i], ShouldEqual, v)
assert.Equal(t, v, values[i])
}
}
func int64sEqual(values []int64, expected ...int64) {
So(values, ShouldHaveLength, len(expected))
func int64sEqual(t *testing.T, values []int64, expected ...int64) {
t.Helper()
assert.Len(t, values, len(expected))
for i, v := range expected {
So(values[i], ShouldEqual, v)
assert.Equal(t, v, values[i])
}
}
func uintsEqual(values []uint, expected ...uint) {
So(values, ShouldHaveLength, len(expected))
func uintsEqual(t *testing.T, values []uint, expected ...uint) {
t.Helper()
assert.Len(t, values, len(expected))
for i, v := range expected {
So(values[i], ShouldEqual, v)
assert.Equal(t, v, values[i])
}
}
func uint64sEqual(values []uint64, expected ...uint64) {
So(values, ShouldHaveLength, len(expected))
func uint64sEqual(t *testing.T, values []uint64, expected ...uint64) {
t.Helper()
assert.Len(t, values, len(expected))
for i, v := range expected {
So(values[i], ShouldEqual, v)
assert.Equal(t, v, values[i])
}
}
func boolsEqual(values []bool, expected ...bool) {
So(values, ShouldHaveLength, len(expected))
func boolsEqual(t *testing.T, values []bool, expected ...bool) {
t.Helper()
assert.Len(t, values, len(expected))
for i, v := range expected {
So(values[i], ShouldEqual, v)
assert.Equal(t, v, values[i])
}
}
func timesEqual(values []time.Time, expected ...time.Time) {
So(values, ShouldHaveLength, len(expected))
func timesEqual(t *testing.T, values []time.Time, expected ...time.Time) {
t.Helper()
assert.Len(t, values, len(expected))
for i, v := range expected {
So(values[i].String(), ShouldEqual, v.String())
assert.Equal(t, v.String(), values[i].String())
}
}
func TestKey_Helpers(t *testing.T) {
Convey("Getting and setting values", t, func() {
t.Run("getting and setting values", func(t *testing.T) {
f, err := ini.Load(fullConf)
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
Convey("Get string representation", func() {
t.Run("get string representation", func(t *testing.T) {
sec := f.Section("")
So(sec, ShouldNotBeNil)
So(sec.Key("NAME").Value(), ShouldEqual, "ini")
So(sec.Key("NAME").String(), ShouldEqual, "ini")
So(sec.Key("NAME").Validate(func(in string) string {
require.NotNil(t, sec)
assert.Equal(t, "ini", sec.Key("NAME").Value())
assert.Equal(t, "ini", sec.Key("NAME").String())
assert.Equal(t, "ini", sec.Key("NAME").Validate(func(in string) string {
return in
}), ShouldEqual, "ini")
So(sec.Key("NAME").Comment, ShouldEqual, "; Package name")
So(sec.Key("IMPORT_PATH").String(), ShouldEqual, "gopkg.in/ini.v1")
}))
assert.Equal(t, "; Package name", sec.Key("NAME").Comment)
assert.Equal(t, "gopkg.in/ini.v1", sec.Key("IMPORT_PATH").String())
Convey("With ValueMapper", func() {
t.Run("with ValueMapper", func(t *testing.T) {
f.ValueMapper = func(in string) string {
if in == "gopkg.in/%(NAME)s.%(VERSION)s" {
return "github.com/go-ini/ini"
}
return in
}
So(sec.Key("IMPORT_PATH").String(), ShouldEqual, "github.com/go-ini/ini")
assert.Equal(t, "github.com/go-ini/ini", sec.Key("IMPORT_PATH").String())
})
})
Convey("Get values in non-default section", func() {
t.Run("get values in non-default section", func(t *testing.T) {
sec := f.Section("author")
So(sec, ShouldNotBeNil)
So(sec.Key("NAME").String(), ShouldEqual, "Unknwon")
So(sec.Key("GITHUB").String(), ShouldEqual, "https://github.com/Unknwon")
require.NotNil(t, sec)
assert.Equal(t, "Unknwon", sec.Key("NAME").String())
assert.Equal(t, "https://github.com/Unknwon", sec.Key("GITHUB").String())
sec = f.Section("package")
So(sec, ShouldNotBeNil)
So(sec.Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
require.NotNil(t, sec)
assert.Equal(t, "https://gopkg.in/ini.v1", sec.Key("CLONE_URL").String())
})
Convey("Get auto-increment key names", func() {
t.Run("get auto-increment key names", func(t *testing.T) {
keys := f.Section("features").Keys()
for i, k := range keys {
So(k.Name(), ShouldEqual, fmt.Sprintf("#%d", i+1))
assert.Equal(t, fmt.Sprintf("#%d", i+1), k.Name())
}
})
Convey("Get parent-keys that are available to the child section", func() {
t.Run("get parent-keys that are available to the child section", func(t *testing.T) {
parentKeys := f.Section("package.sub").ParentKeys()
for _, k := range parentKeys {
So(k.Name(), ShouldEqual, "CLONE_URL")
assert.Equal(t, "CLONE_URL", k.Name())
}
})
Convey("Get overwrite value", func() {
So(f.Section("author").Key("E-MAIL").String(), ShouldEqual, "u@gogs.io")
t.Run("get overwrite value", func(t *testing.T) {
assert.Equal(t, "u@gogs.io", f.Section("author").Key("E-MAIL").String())
})
Convey("Get sections", func() {
t.Run("get sections", func(t *testing.T) {
sections := f.Sections()
for i, name := range []string{ini.DefaultSection, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "string escapes", "advance"} {
So(sections[i].Name(), ShouldEqual, name)
assert.Equal(t, name, sections[i].Name())
}
})
Convey("Get parent section value", func() {
So(f.Section("package.sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
So(f.Section("package.fake.sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
t.Run("get parent section value", func(t *testing.T) {
assert.Equal(t, "https://gopkg.in/ini.v1", f.Section("package.sub").Key("CLONE_URL").String())
assert.Equal(t, "https://gopkg.in/ini.v1", f.Section("package.fake.sub").Key("CLONE_URL").String())
})
Convey("Get multiple line value", func() {
t.Run("get multiple line value", func(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("Skipping testing on Windows")
}
So(f.Section("author").Key("BIO").String(), ShouldEqual, "Gopher.\nCoding addict.\nGood man.\n")
assert.Equal(t, "Gopher.\nCoding addict.\nGood man.\n", f.Section("author").Key("BIO").String())
})
Convey("Get values with type", func() {
t.Run("get values with type", func(t *testing.T) {
sec := f.Section("types")
v1, err := sec.Key("BOOL").Bool()
So(err, ShouldBeNil)
So(v1, ShouldBeTrue)
require.NoError(t, err)
assert.True(t, v1)
v1, err = sec.Key("BOOL_FALSE").Bool()
So(err, ShouldBeNil)
So(v1, ShouldBeFalse)
require.NoError(t, err)
assert.False(t, v1)
v2, err := sec.Key("FLOAT64").Float64()
So(err, ShouldBeNil)
So(v2, ShouldEqual, 1.25)
require.NoError(t, err)
assert.Equal(t, 1.25, v2)
v3, err := sec.Key("INT").Int()
So(err, ShouldBeNil)
So(v3, ShouldEqual, 10)
require.NoError(t, err)
assert.Equal(t, 10, v3)
v4, err := sec.Key("INT").Int64()
So(err, ShouldBeNil)
So(v4, ShouldEqual, 10)
require.NoError(t, err)
assert.Equal(t, int64(10), v4)
v5, err := sec.Key("UINT").Uint()
So(err, ShouldBeNil)
So(v5, ShouldEqual, 3)
require.NoError(t, err)
assert.Equal(t, uint(3), v5)
v6, err := sec.Key("UINT").Uint64()
So(err, ShouldBeNil)
So(v6, ShouldEqual, 3)
require.NoError(t, err)
assert.Equal(t, uint64(3), v6)
t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
So(err, ShouldBeNil)
ti, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
require.NoError(t, err)
v7, err := sec.Key("TIME").Time()
So(err, ShouldBeNil)
So(v7.String(), ShouldEqual, t.String())
require.NoError(t, err)
assert.Equal(t, ti.String(), v7.String())
v8, err := sec.Key("HEX_NUMBER").Int()
So(err, ShouldBeNil)
So(v8, ShouldEqual, 0x3000)
require.NoError(t, err)
assert.Equal(t, 0x3000, v8)
Convey("Must get values with type", func() {
So(sec.Key("STRING").MustString("404"), ShouldEqual, "str")
So(sec.Key("BOOL").MustBool(), ShouldBeTrue)
So(sec.Key("FLOAT64").MustFloat64(), ShouldEqual, 1.25)
So(sec.Key("INT").MustInt(), ShouldEqual, 10)
So(sec.Key("INT").MustInt64(), ShouldEqual, 10)
So(sec.Key("UINT").MustUint(), ShouldEqual, 3)
So(sec.Key("UINT").MustUint64(), ShouldEqual, 3)
So(sec.Key("TIME").MustTime().String(), ShouldEqual, t.String())
So(sec.Key("HEX_NUMBER").MustInt(), ShouldEqual, 0x3000)
t.Run("must get values with type", func(t *testing.T) {
assert.Equal(t, "str", sec.Key("STRING").MustString("404"))
assert.True(t, sec.Key("BOOL").MustBool())
assert.Equal(t, float64(1.25), sec.Key("FLOAT64").MustFloat64())
assert.Equal(t, int(10), sec.Key("INT").MustInt())
assert.Equal(t, int64(10), sec.Key("INT").MustInt64())
assert.Equal(t, uint(3), sec.Key("UINT").MustUint())
assert.Equal(t, uint64(3), sec.Key("UINT").MustUint64())
assert.Equal(t, ti.String(), sec.Key("TIME").MustTime().String())
assert.Equal(t, 0x3000, sec.Key("HEX_NUMBER").MustInt())
dur, err := time.ParseDuration("2h45m")
So(err, ShouldBeNil)
So(sec.Key("DURATION").MustDuration().Seconds(), ShouldEqual, dur.Seconds())
require.NoError(t, err)
assert.Equal(t, dur.Seconds(), sec.Key("DURATION").MustDuration().Seconds())
Convey("Must get values with default value", func() {
So(sec.Key("STRING_404").MustString("404"), ShouldEqual, "404")
So(sec.Key("BOOL_404").MustBool(true), ShouldBeTrue)
So(sec.Key("FLOAT64_404").MustFloat64(2.5), ShouldEqual, 2.5)
So(sec.Key("INT_404").MustInt(15), ShouldEqual, 15)
So(sec.Key("INT64_404").MustInt64(15), ShouldEqual, 15)
So(sec.Key("UINT_404").MustUint(6), ShouldEqual, 6)
So(sec.Key("UINT64_404").MustUint64(6), ShouldEqual, 6)
So(sec.Key("HEX_NUMBER_404").MustInt(0x3001), ShouldEqual, 0x3001)
t.Run("must get values with default value", func(t *testing.T) {
assert.Equal(t, "404", sec.Key("STRING_404").MustString("404"))
assert.True(t, sec.Key("BOOL_404").MustBool(true))
assert.Equal(t, float64(2.5), sec.Key("FLOAT64_404").MustFloat64(2.5))
assert.Equal(t, int(15), sec.Key("INT_404").MustInt(15))
assert.Equal(t, int64(15), sec.Key("INT64_404").MustInt64(15))
assert.Equal(t, uint(6), sec.Key("UINT_404").MustUint(6))
assert.Equal(t, uint64(6), sec.Key("UINT64_404").MustUint64(6))
assert.Equal(t, 0x3001, sec.Key("HEX_NUMBER_404").MustInt(0x3001))
t, err := time.Parse(time.RFC3339, "2014-01-01T20:17:05Z")
So(err, ShouldBeNil)
So(sec.Key("TIME_404").MustTime(t).String(), ShouldEqual, t.String())
ti, err := time.Parse(time.RFC3339, "2014-01-01T20:17:05Z")
require.NoError(t, err)
assert.Equal(t, ti.String(), sec.Key("TIME_404").MustTime(ti).String())
So(sec.Key("DURATION_404").MustDuration(dur).Seconds(), ShouldEqual, dur.Seconds())
assert.Equal(t, dur.Seconds(), sec.Key("DURATION_404").MustDuration(dur).Seconds())
Convey("Must should set default as key value", func() {
So(sec.Key("STRING_404").String(), ShouldEqual, "404")
So(sec.Key("BOOL_404").String(), ShouldEqual, "true")
So(sec.Key("FLOAT64_404").String(), ShouldEqual, "2.5")
So(sec.Key("INT_404").String(), ShouldEqual, "15")
So(sec.Key("INT64_404").String(), ShouldEqual, "15")
So(sec.Key("UINT_404").String(), ShouldEqual, "6")
So(sec.Key("UINT64_404").String(), ShouldEqual, "6")
So(sec.Key("TIME_404").String(), ShouldEqual, "2014-01-01T20:17:05Z")
So(sec.Key("DURATION_404").String(), ShouldEqual, "2h45m0s")
So(sec.Key("HEX_NUMBER_404").String(), ShouldEqual, "12289")
t.Run("must should set default as key value", func(t *testing.T) {
assert.Equal(t, "404", sec.Key("STRING_404").String())
assert.Equal(t, "true", sec.Key("BOOL_404").String())
assert.Equal(t, "2.5", sec.Key("FLOAT64_404").String())
assert.Equal(t, "15", sec.Key("INT_404").String())
assert.Equal(t, "15", sec.Key("INT64_404").String())
assert.Equal(t, "6", sec.Key("UINT_404").String())
assert.Equal(t, "6", sec.Key("UINT64_404").String())
assert.Equal(t, "2014-01-01T20:17:05Z", sec.Key("TIME_404").String())
assert.Equal(t, "2h45m0s", sec.Key("DURATION_404").String())
assert.Equal(t, "12289", sec.Key("HEX_NUMBER_404").String())
})
})
})
})
Convey("Get value with candidates", func() {
t.Run("get value with candidates", func(t *testing.T) {
sec := f.Section("types")
So(sec.Key("STRING").In("", []string{"str", "arr", "types"}), ShouldEqual, "str")
So(sec.Key("FLOAT64").InFloat64(0, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25)
So(sec.Key("INT").InInt(0, []int{10, 20, 30}), ShouldEqual, 10)
So(sec.Key("INT").InInt64(0, []int64{10, 20, 30}), ShouldEqual, 10)
So(sec.Key("UINT").InUint(0, []uint{3, 6, 9}), ShouldEqual, 3)
So(sec.Key("UINT").InUint64(0, []uint64{3, 6, 9}), ShouldEqual, 3)
assert.Equal(t, "str", sec.Key("STRING").In("", []string{"str", "arr", "types"}))
assert.Equal(t, float64(1.25), sec.Key("FLOAT64").InFloat64(0, []float64{1.25, 2.5, 3.75}))
assert.Equal(t, int(10), sec.Key("INT").InInt(0, []int{10, 20, 30}))
assert.Equal(t, int64(10), sec.Key("INT").InInt64(0, []int64{10, 20, 30}))
assert.Equal(t, uint(3), sec.Key("UINT").InUint(0, []uint{3, 6, 9}))
assert.Equal(t, uint64(3), sec.Key("UINT").InUint64(0, []uint64{3, 6, 9}))
zt, err := time.Parse(time.RFC3339, "0001-01-01T01:00:00Z")
So(err, ShouldBeNil)
t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
So(err, ShouldBeNil)
So(sec.Key("TIME").InTime(zt, []time.Time{t, time.Now(), time.Now().Add(1 * time.Second)}).String(), ShouldEqual, t.String())
require.NoError(t, err)
ti, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
require.NoError(t, err)
assert.Equal(t, ti.String(), sec.Key("TIME").InTime(zt, []time.Time{ti, time.Now(), time.Now().Add(1 * time.Second)}).String())
Convey("Get value with candidates and default value", func() {
So(sec.Key("STRING_404").In("str", []string{"str", "arr", "types"}), ShouldEqual, "str")
So(sec.Key("FLOAT64_404").InFloat64(1.25, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25)
So(sec.Key("INT_404").InInt(10, []int{10, 20, 30}), ShouldEqual, 10)
So(sec.Key("INT64_404").InInt64(10, []int64{10, 20, 30}), ShouldEqual, 10)
So(sec.Key("UINT_404").InUint(3, []uint{3, 6, 9}), ShouldEqual, 3)
So(sec.Key("UINT_404").InUint64(3, []uint64{3, 6, 9}), ShouldEqual, 3)
So(sec.Key("TIME_404").InTime(t, []time.Time{time.Now(), time.Now(), time.Now().Add(1 * time.Second)}).String(), ShouldEqual, t.String())
t.Run("get value with candidates and default value", func(t *testing.T) {
assert.Equal(t, "str", sec.Key("STRING_404_2").In("str", []string{"str", "arr", "types"}))
assert.Equal(t, float64(1.25), sec.Key("FLOAT64_404_2").InFloat64(1.25, []float64{1.25, 2.5, 3.75}))
assert.Equal(t, int(10), sec.Key("INT_404_2").InInt(10, []int{10, 20, 30}))
assert.Equal(t, int64(10), sec.Key("INT64_404_2").InInt64(10, []int64{10, 20, 30}))
assert.Equal(t, uint(3), sec.Key("UINT_404_2").InUint(3, []uint{3, 6, 9}))
assert.Equal(t, uint64(3), sec.Key("UINT_404_2").InUint64(3, []uint64{3, 6, 9}))
assert.Equal(t, ti.String(), sec.Key("TIME_404_2").InTime(ti, []time.Time{time.Now(), time.Now(), time.Now().Add(1 * time.Second)}).String())
})
})
Convey("Get values in range", func() {
t.Run("get values in range", func(t *testing.T) {
sec := f.Section("types")
So(sec.Key("FLOAT64").RangeFloat64(0, 1, 2), ShouldEqual, 1.25)
So(sec.Key("INT").RangeInt(0, 10, 20), ShouldEqual, 10)
So(sec.Key("INT").RangeInt64(0, 10, 20), ShouldEqual, 10)
assert.Equal(t, float64(1.25), sec.Key("FLOAT64").RangeFloat64(0, 1, 2))
assert.Equal(t, int(10), sec.Key("INT").RangeInt(0, 10, 20))
assert.Equal(t, int64(10), sec.Key("INT").RangeInt64(0, 10, 20))
minT, err := time.Parse(time.RFC3339, "0001-01-01T01:00:00Z")
So(err, ShouldBeNil)
require.NoError(t, err)
midT, err := time.Parse(time.RFC3339, "2013-01-01T01:00:00Z")
So(err, ShouldBeNil)
require.NoError(t, err)
maxT, err := time.Parse(time.RFC3339, "9999-01-01T01:00:00Z")
So(err, ShouldBeNil)
t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
So(err, ShouldBeNil)
So(sec.Key("TIME").RangeTime(t, minT, maxT).String(), ShouldEqual, t.String())
require.NoError(t, err)
ti, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
require.NoError(t, err)
assert.Equal(t, ti.String(), sec.Key("TIME").RangeTime(ti, minT, maxT).String())
Convey("Get value in range with default value", func() {
So(sec.Key("FLOAT64").RangeFloat64(5, 0, 1), ShouldEqual, 5)
So(sec.Key("INT").RangeInt(7, 0, 5), ShouldEqual, 7)
So(sec.Key("INT").RangeInt64(7, 0, 5), ShouldEqual, 7)
So(sec.Key("TIME").RangeTime(t, minT, midT).String(), ShouldEqual, t.String())
t.Run("get value in range with default value", func(t *testing.T) {
assert.Equal(t, float64(5), sec.Key("FLOAT64").RangeFloat64(5, 0, 1))
assert.Equal(t, 7, sec.Key("INT").RangeInt(7, 0, 5))
assert.Equal(t, int64(7), sec.Key("INT").RangeInt64(7, 0, 5))
assert.Equal(t, ti.String(), sec.Key("TIME").RangeTime(ti, minT, midT).String())
})
})
Convey("Get values into slice", func() {
t.Run("get values into slice", func(t *testing.T) {
sec := f.Section("array")
So(strings.Join(sec.Key("STRINGS").Strings(","), ","), ShouldEqual, "en,zh,de")
So(len(sec.Key("STRINGS_404").Strings(",")), ShouldEqual, 0)
assert.Equal(t, "en,zh,de", strings.Join(sec.Key("STRINGS").Strings(","), ","))
assert.Equal(t, 0, len(sec.Key("STRINGS_404").Strings(",")))
vals1 := sec.Key("FLOAT64S").Float64s(",")
float64sEqual(vals1, 1.1, 2.2, 3.3)
float64sEqual(t, vals1, 1.1, 2.2, 3.3)
vals2 := sec.Key("INTS").Ints(",")
intsEqual(vals2, 1, 2, 3)
intsEqual(t, vals2, 1, 2, 3)
vals3 := sec.Key("INTS").Int64s(",")
int64sEqual(vals3, 1, 2, 3)
int64sEqual(t, vals3, 1, 2, 3)
vals4 := sec.Key("UINTS").Uints(",")
uintsEqual(vals4, 1, 2, 3)
uintsEqual(t, vals4, 1, 2, 3)
vals5 := sec.Key("UINTS").Uint64s(",")
uint64sEqual(vals5, 1, 2, 3)
uint64sEqual(t, vals5, 1, 2, 3)
vals6 := sec.Key("BOOLS").Bools(",")
boolsEqual(vals6, true, false, false)
boolsEqual(t, vals6, true, false, false)
t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
So(err, ShouldBeNil)
ti, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
require.NoError(t, err)
vals7 := sec.Key("TIMES").Times(",")
timesEqual(vals7, t, t, t)
timesEqual(t, vals7, ti, ti, ti)
})
Convey("Test string slice escapes", func() {
t.Run("test string slice escapes", func(t *testing.T) {
sec := f.Section("string escapes")
So(sec.Key("key1").Strings(","), ShouldResemble, []string{"value1", "value2", "value3"})
So(sec.Key("key2").Strings(","), ShouldResemble, []string{"value1, value2"})
So(sec.Key("key3").Strings(","), ShouldResemble, []string{`val\ue1`, "value2"})
So(sec.Key("key4").Strings(","), ShouldResemble, []string{`value1\`, `value\\2`})
So(sec.Key("key5").Strings(",,"), ShouldResemble, []string{"value1,, value2"})
So(sec.Key("key6").Strings(" "), ShouldResemble, []string{"aaa", "bbb and space", "ccc"})
assert.Equal(t, []string{"value1", "value2", "value3"}, sec.Key("key1").Strings(","))
assert.Equal(t, []string{"value1, value2"}, sec.Key("key2").Strings(","))
assert.Equal(t, []string{`val\ue1`, "value2"}, sec.Key("key3").Strings(","))
assert.Equal(t, []string{`value1\`, `value\\2`}, sec.Key("key4").Strings(","))
assert.Equal(t, []string{"value1,, value2"}, sec.Key("key5").Strings(",,"))
assert.Equal(t, []string{"aaa", "bbb and space", "ccc"}, sec.Key("key6").Strings(" "))
})
Convey("Get valid values into slice", func() {
t.Run("get valid values into slice", func(t *testing.T) {
sec := f.Section("array")
vals1 := sec.Key("FLOAT64S").ValidFloat64s(",")
float64sEqual(vals1, 1.1, 2.2, 3.3)
float64sEqual(t, vals1, 1.1, 2.2, 3.3)
vals2 := sec.Key("INTS").ValidInts(",")
intsEqual(vals2, 1, 2, 3)
intsEqual(t, vals2, 1, 2, 3)
vals3 := sec.Key("INTS").ValidInt64s(",")
int64sEqual(vals3, 1, 2, 3)
int64sEqual(t, vals3, 1, 2, 3)
vals4 := sec.Key("UINTS").ValidUints(",")
uintsEqual(vals4, 1, 2, 3)
uintsEqual(t, vals4, 1, 2, 3)
vals5 := sec.Key("UINTS").ValidUint64s(",")
uint64sEqual(vals5, 1, 2, 3)
uint64sEqual(t, vals5, 1, 2, 3)
vals6 := sec.Key("BOOLS").ValidBools(",")
boolsEqual(vals6, true, false, false)
boolsEqual(t, vals6, true, false, false)
t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
So(err, ShouldBeNil)
ti, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
require.NoError(t, err)
vals7 := sec.Key("TIMES").ValidTimes(",")
timesEqual(vals7, t, t, t)
timesEqual(t, vals7, ti, ti, ti)
})
Convey("Get values one type into slice of another type", func() {
t.Run("get values one type into slice of another type", func(t *testing.T) {
sec := f.Section("array")
vals1 := sec.Key("STRINGS").ValidFloat64s(",")
So(vals1, ShouldBeEmpty)
assert.Empty(t, vals1)
vals2 := sec.Key("STRINGS").ValidInts(",")
So(vals2, ShouldBeEmpty)
assert.Empty(t, vals2)
vals3 := sec.Key("STRINGS").ValidInt64s(",")
So(vals3, ShouldBeEmpty)
assert.Empty(t, vals3)
vals4 := sec.Key("STRINGS").ValidUints(",")
So(vals4, ShouldBeEmpty)
assert.Empty(t, vals4)
vals5 := sec.Key("STRINGS").ValidUint64s(",")
So(vals5, ShouldBeEmpty)
assert.Empty(t, vals5)
vals6 := sec.Key("STRINGS").ValidBools(",")
So(vals6, ShouldBeEmpty)
assert.Empty(t, vals6)
vals7 := sec.Key("STRINGS").ValidTimes(",")
So(vals7, ShouldBeEmpty)
assert.Empty(t, vals7)
})
Convey("Get valid values into slice without errors", func() {
t.Run("get valid values into slice without errors", func(t *testing.T) {
sec := f.Section("array")
vals1, err := sec.Key("FLOAT64S").StrictFloat64s(",")
So(err, ShouldBeNil)
float64sEqual(vals1, 1.1, 2.2, 3.3)
require.NoError(t, err)
float64sEqual(t, vals1, 1.1, 2.2, 3.3)
vals2, err := sec.Key("INTS").StrictInts(",")
So(err, ShouldBeNil)
intsEqual(vals2, 1, 2, 3)
require.NoError(t, err)
intsEqual(t, vals2, 1, 2, 3)
vals3, err := sec.Key("INTS").StrictInt64s(",")
So(err, ShouldBeNil)
int64sEqual(vals3, 1, 2, 3)
require.NoError(t, err)
int64sEqual(t, vals3, 1, 2, 3)
vals4, err := sec.Key("UINTS").StrictUints(",")
So(err, ShouldBeNil)
uintsEqual(vals4, 1, 2, 3)
require.NoError(t, err)
uintsEqual(t, vals4, 1, 2, 3)
vals5, err := sec.Key("UINTS").StrictUint64s(",")
So(err, ShouldBeNil)
uint64sEqual(vals5, 1, 2, 3)
require.NoError(t, err)
uint64sEqual(t, vals5, 1, 2, 3)
vals6, err := sec.Key("BOOLS").StrictBools(",")
So(err, ShouldBeNil)
boolsEqual(vals6, true, false, false)
require.NoError(t, err)
boolsEqual(t, vals6, true, false, false)
t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
So(err, ShouldBeNil)
ti, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
require.NoError(t, err)
vals7, err := sec.Key("TIMES").StrictTimes(",")
So(err, ShouldBeNil)
timesEqual(vals7, t, t, t)
require.NoError(t, err)
timesEqual(t, vals7, ti, ti, ti)
})
Convey("Get invalid values into slice", func() {
t.Run("get invalid values into slice", func(t *testing.T) {
sec := f.Section("array")
vals1, err := sec.Key("STRINGS").StrictFloat64s(",")
So(vals1, ShouldBeEmpty)
So(err, ShouldNotBeNil)
assert.Empty(t, vals1)
assert.Error(t, err)
vals2, err := sec.Key("STRINGS").StrictInts(",")
So(vals2, ShouldBeEmpty)
So(err, ShouldNotBeNil)
assert.Empty(t, vals2)
assert.Error(t, err)
vals3, err := sec.Key("STRINGS").StrictInt64s(",")
So(vals3, ShouldBeEmpty)
So(err, ShouldNotBeNil)
assert.Empty(t, vals3)
assert.Error(t, err)
vals4, err := sec.Key("STRINGS").StrictUints(",")
So(vals4, ShouldBeEmpty)
So(err, ShouldNotBeNil)
assert.Empty(t, vals4)
assert.Error(t, err)
vals5, err := sec.Key("STRINGS").StrictUint64s(",")
So(vals5, ShouldBeEmpty)
So(err, ShouldNotBeNil)
assert.Empty(t, vals5)
assert.Error(t, err)
vals6, err := sec.Key("STRINGS").StrictBools(",")
So(vals6, ShouldBeEmpty)
So(err, ShouldNotBeNil)
assert.Empty(t, vals6)
assert.Error(t, err)
vals7, err := sec.Key("STRINGS").StrictTimes(",")
So(vals7, ShouldBeEmpty)
So(err, ShouldNotBeNil)
assert.Empty(t, vals7)
assert.Error(t, err)
})
})
}
func TestKey_StringsWithShadows(t *testing.T) {
Convey("Get strings of shadows of a key", t, func() {
t.Run("get strings of shadows of a key", func(t *testing.T) {
f, err := ini.ShadowLoad([]byte(""))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
k, err := f.Section("").NewKey("NUMS", "1,2")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
k, err = f.Section("").NewKey("NUMS", "4,5,6")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
So(k.StringsWithShadows(","), ShouldResemble, []string{"1", "2", "4", "5", "6"})
assert.Equal(t, []string{"1", "2", "4", "5", "6"}, k.StringsWithShadows(","))
})
}
func TestKey_SetValue(t *testing.T) {
Convey("Set value of key", t, func() {
t.Run("set value of key", func(t *testing.T) {
f := ini.Empty()
So(f, ShouldNotBeNil)
require.NotNil(t, f)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
So(k.Value(), ShouldEqual, "ini")
require.NoError(t, err)
require.NotNil(t, k)
assert.Equal(t, "ini", k.Value())
k.SetValue("ini.v1")
So(k.Value(), ShouldEqual, "ini.v1")
assert.Equal(t, "ini.v1", k.Value())
})
}
func TestKey_NestedValues(t *testing.T) {
Convey("Read and write nested values", t, func() {
t.Run("read and write nested values", func(t *testing.T) {
f, err := ini.LoadSources(ini.LoadOptions{
AllowNestedValues: true,
}, []byte(`
@@ -550,48 +566,50 @@ region = us-west-2
s3 =
max_concurrent_requests=10
max_queue_size=1000`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
So(f.Section("").Key("s3").NestedValues(), ShouldResemble, []string{"max_concurrent_requests=10", "max_queue_size=1000"})
assert.Equal(t, []string{"max_concurrent_requests=10", "max_queue_size=1000"}, f.Section("").Key("s3").NestedValues())
var buf bytes.Buffer
_, err = f.WriteTo(&buf)
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, `aws_access_key_id = foo
require.NoError(t, err)
assert.Equal(t, `aws_access_key_id = foo
aws_secret_access_key = bar
region = us-west-2
s3 =
max_concurrent_requests=10
max_queue_size=1000
`)
`,
buf.String(),
)
})
}
func TestRecursiveValues(t *testing.T) {
Convey("Recursive values should not reflect on same key", t, func() {
t.Run("recursive values should not reflect on same key", func(t *testing.T) {
f, err := ini.Load([]byte(`
NAME = ini
expires = yes
[package]
NAME = %(NAME)s
expires = %(expires)s`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
So(f.Section("package").Key("NAME").String(), ShouldEqual, "ini")
So(f.Section("package").Key("expires").String(), ShouldEqual, "yes")
assert.Equal(t, "ini", f.Section("package").Key("NAME").String())
assert.Equal(t, "yes", f.Section("package").Key("expires").String())
})
Convey("Recursive value with no target found", t, func() {
t.Run("recursive value with no target found", func(t *testing.T) {
f, err := ini.Load([]byte(`
[foo]
bar = %(missing)s
`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
So(f.Section("foo").Key("bar").String(), ShouldEqual, "%(missing)s")
assert.Equal(t, "%(missing)s", f.Section("foo").Key("bar").String())
})
}
+24 -22
View File
@@ -17,61 +17,63 @@ package ini_test
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/ini.v1"
)
func TestBOM(t *testing.T) {
Convey("Test handling BOM", t, func() {
Convey("UTF-8-BOM", func() {
t.Run("test handling BOM", func(t *testing.T) {
t.Run("UTF-8-BOM", func(t *testing.T) {
f, err := ini.Load("testdata/UTF-8-BOM.ini")
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
So(f.Section("author").Key("E-MAIL").String(), ShouldEqual, "example@email.com")
assert.Equal(t, "example@email.com", f.Section("author").Key("E-MAIL").String())
})
Convey("UTF-16-LE-BOM", func() {
t.Run("UTF-16-LE-BOM", func(t *testing.T) {
f, err := ini.Load("testdata/UTF-16-LE-BOM.ini")
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
})
Convey("UTF-16-BE-BOM", func() {
t.Run("UTF-16-BE-BOM", func(t *testing.T) {
})
})
}
func TestBadLoad(t *testing.T) {
Convey("Load with bad data", t, func() {
Convey("Bad section name", func() {
t.Run("load with bad data", func(t *testing.T) {
t.Run("bad section name", func(t *testing.T) {
_, err := ini.Load([]byte("[]"))
So(err, ShouldNotBeNil)
require.Error(t, err)
_, err = ini.Load([]byte("["))
So(err, ShouldNotBeNil)
require.Error(t, err)
})
Convey("Bad keys", func() {
t.Run("bad keys", func(t *testing.T) {
_, err := ini.Load([]byte(`"""name`))
So(err, ShouldNotBeNil)
require.Error(t, err)
_, err = ini.Load([]byte(`"""name"""`))
So(err, ShouldNotBeNil)
require.Error(t, err)
_, err = ini.Load([]byte(`""=1`))
So(err, ShouldNotBeNil)
require.Error(t, err)
_, err = ini.Load([]byte(`=`))
So(err, ShouldNotBeNil)
require.Error(t, err)
_, err = ini.Load([]byte(`name`))
So(err, ShouldNotBeNil)
require.Error(t, err)
})
Convey("Bad values", func() {
t.Run("bad values", func(t *testing.T) {
_, err := ini.Load([]byte(`name="""Unknwon`))
So(err, ShouldNotBeNil)
require.Error(t, err)
})
})
}
+128 -126
View File
@@ -17,261 +17,263 @@ package ini_test
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/ini.v1"
)
func TestSection_SetBody(t *testing.T) {
Convey("Set body of raw section", t, func() {
t.Run("set body of raw section", func(t *testing.T) {
f := ini.Empty()
So(f, ShouldNotBeNil)
require.NotNil(t, f)
sec, err := f.NewRawSection("comments", `1111111111111111111000000000000000001110000
111111111111111111100000000000111000000000`)
So(err, ShouldBeNil)
So(sec, ShouldNotBeNil)
So(sec.Body(), ShouldEqual, `1111111111111111111000000000000000001110000
111111111111111111100000000000111000000000`)
require.NoError(t, err)
require.NotNil(t, sec)
assert.Equal(t, `1111111111111111111000000000000000001110000
111111111111111111100000000000111000000000`, sec.Body())
sec.SetBody("1111111111111111111000000000000000001110000")
So(sec.Body(), ShouldEqual, `1111111111111111111000000000000000001110000`)
assert.Equal(t, `1111111111111111111000000000000000001110000`, sec.Body())
Convey("Set for non-raw section", func() {
t.Run("set for non-raw section", func(t *testing.T) {
sec, err := f.NewSection("author")
So(err, ShouldBeNil)
So(sec, ShouldNotBeNil)
So(sec.Body(), ShouldBeEmpty)
require.NoError(t, err)
require.NotNil(t, sec)
assert.Empty(t, sec.Body())
sec.SetBody("1111111111111111111000000000000000001110000")
So(sec.Body(), ShouldBeEmpty)
assert.Empty(t, sec.Body())
})
})
}
func TestSection_NewKey(t *testing.T) {
Convey("Create a new key", t, func() {
t.Run("create a new key", func(t *testing.T) {
f := ini.Empty()
So(f, ShouldNotBeNil)
require.NotNil(t, f)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
So(k.Name(), ShouldEqual, "NAME")
So(k.Value(), ShouldEqual, "ini")
require.NoError(t, err)
require.NotNil(t, k)
assert.Equal(t, "NAME", k.Name())
assert.Equal(t, "ini", k.Value())
Convey("With duplicated name", func() {
t.Run("with duplicated name", func(t *testing.T) {
k, err := f.Section("").NewKey("NAME", "ini.v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
// Overwrite previous existed key
So(k.Value(), ShouldEqual, "ini.v1")
assert.Equal(t, "ini.v1", k.Value())
})
Convey("With empty string", func() {
t.Run("with empty string", func(t *testing.T) {
_, err := f.Section("").NewKey("", "")
So(err, ShouldNotBeNil)
require.Error(t, err)
})
})
Convey("Create keys with same name and allow shadow", t, func() {
t.Run("create keys with same name and allow shadow", func(t *testing.T) {
f, err := ini.ShadowLoad([]byte(""))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
k, err = f.Section("").NewKey("NAME", "ini.v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
So(k.ValueWithShadows(), ShouldResemble, []string{"ini", "ini.v1"})
assert.Equal(t, []string{"ini", "ini.v1"}, k.ValueWithShadows())
})
}
func TestSection_NewBooleanKey(t *testing.T) {
Convey("Create a new boolean key", t, func() {
t.Run("create a new boolean key", func(t *testing.T) {
f := ini.Empty()
So(f, ShouldNotBeNil)
require.NotNil(t, f)
k, err := f.Section("").NewBooleanKey("start-ssh-server")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
So(k.Name(), ShouldEqual, "start-ssh-server")
So(k.Value(), ShouldEqual, "true")
require.NoError(t, err)
require.NotNil(t, k)
assert.Equal(t, "start-ssh-server", k.Name())
assert.Equal(t, "true", k.Value())
Convey("With empty string", func() {
t.Run("with empty string", func(t *testing.T) {
_, err := f.Section("").NewBooleanKey("")
So(err, ShouldNotBeNil)
require.Error(t, err)
})
})
}
func TestSection_GetKey(t *testing.T) {
Convey("Get a key", t, func() {
t.Run("get a key", func(t *testing.T) {
f := ini.Empty()
So(f, ShouldNotBeNil)
require.NotNil(t, f)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
k, err = f.Section("").GetKey("NAME")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
So(k.Name(), ShouldEqual, "NAME")
So(k.Value(), ShouldEqual, "ini")
require.NoError(t, err)
require.NotNil(t, k)
assert.Equal(t, "NAME", k.Name())
assert.Equal(t, "ini", k.Value())
Convey("Key not exists", func() {
t.Run("key not exists", func(t *testing.T) {
_, err := f.Section("").GetKey("404")
So(err, ShouldNotBeNil)
require.Error(t, err)
})
Convey("Key exists in parent section", func() {
t.Run("key exists in parent section", func(t *testing.T) {
k, err := f.Section("parent").NewKey("AGE", "18")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
k, err = f.Section("parent.child.son").GetKey("AGE")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
So(k.Value(), ShouldEqual, "18")
require.NoError(t, err)
require.NotNil(t, k)
assert.Equal(t, "18", k.Value())
})
})
}
func TestSection_HasKey(t *testing.T) {
Convey("Check if a key exists", t, func() {
t.Run("check if a key exists", func(t *testing.T) {
f := ini.Empty()
So(f, ShouldNotBeNil)
require.NotNil(t, f)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
So(f.Section("").HasKey("NAME"), ShouldBeTrue)
So(f.Section("").HasKey("NAME"), ShouldBeTrue)
So(f.Section("").HasKey("404"), ShouldBeFalse)
So(f.Section("").HasKey("404"), ShouldBeFalse)
assert.True(t, f.Section("").HasKey("NAME"))
assert.True(t, f.Section("").HasKey("NAME"))
assert.False(t, f.Section("").HasKey("404"))
assert.False(t, f.Section("").HasKey("404"))
})
}
func TestSection_HasValue(t *testing.T) {
Convey("Check if contains a value in any key", t, func() {
t.Run("check if contains a value in any key", func(t *testing.T) {
f := ini.Empty()
So(f, ShouldNotBeNil)
require.NotNil(t, f)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
So(f.Section("").HasValue("ini"), ShouldBeTrue)
So(f.Section("").HasValue("404"), ShouldBeFalse)
assert.True(t, f.Section("").HasValue("ini"))
assert.False(t, f.Section("").HasValue("404"))
})
}
func TestSection_Key(t *testing.T) {
Convey("Get a key", t, func() {
t.Run("get a key", func(t *testing.T) {
f := ini.Empty()
So(f, ShouldNotBeNil)
require.NotNil(t, f)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
k = f.Section("").Key("NAME")
So(k, ShouldNotBeNil)
So(k.Name(), ShouldEqual, "NAME")
So(k.Value(), ShouldEqual, "ini")
require.NotNil(t, k)
assert.Equal(t, "NAME", k.Name())
assert.Equal(t, "ini", k.Value())
Convey("Key not exists", func() {
t.Run("key not exists", func(t *testing.T) {
k := f.Section("").Key("404")
So(k, ShouldNotBeNil)
So(k.Name(), ShouldEqual, "404")
require.NotNil(t, k)
assert.Equal(t, "404", k.Name())
})
Convey("Key exists in parent section", func() {
t.Run("key exists in parent section", func(t *testing.T) {
k, err := f.Section("parent").NewKey("AGE", "18")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
k = f.Section("parent.child.son").Key("AGE")
So(k, ShouldNotBeNil)
So(k.Value(), ShouldEqual, "18")
require.NotNil(t, k)
assert.Equal(t, "18", k.Value())
})
})
}
func TestSection_Keys(t *testing.T) {
Convey("Get all keys in a section", t, func() {
t.Run("get all keys in a section", func(t *testing.T) {
f := ini.Empty()
So(f, ShouldNotBeNil)
require.NotNil(t, f)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
k, err = f.Section("").NewKey("VERSION", "v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
k, err = f.Section("").NewKey("IMPORT_PATH", "gopkg.in/ini.v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
keys := f.Section("").Keys()
names := []string{"NAME", "VERSION", "IMPORT_PATH"}
So(len(keys), ShouldEqual, len(names))
assert.Equal(t, len(names), len(keys))
for i, name := range names {
So(keys[i].Name(), ShouldEqual, name)
assert.Equal(t, name, keys[i].Name())
}
})
}
func TestSection_ParentKeys(t *testing.T) {
Convey("Get all keys of parent sections", t, func() {
t.Run("get all keys of parent sections", func(t *testing.T) {
f := ini.Empty()
So(f, ShouldNotBeNil)
require.NotNil(t, f)
k, err := f.Section("package").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
k, err = f.Section("package").NewKey("VERSION", "v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
k, err = f.Section("package").NewKey("IMPORT_PATH", "gopkg.in/ini.v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
keys := f.Section("package.sub.sub2").ParentKeys()
names := []string{"NAME", "VERSION", "IMPORT_PATH"}
So(len(keys), ShouldEqual, len(names))
assert.Equal(t, len(names), len(keys))
for i, name := range names {
So(keys[i].Name(), ShouldEqual, name)
assert.Equal(t, name, keys[i].Name())
}
})
}
func TestSection_KeyStrings(t *testing.T) {
Convey("Get all key names in a section", t, func() {
t.Run("get all key names in a section", func(t *testing.T) {
f := ini.Empty()
So(f, ShouldNotBeNil)
require.NotNil(t, f)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
k, err = f.Section("").NewKey("VERSION", "v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
k, err = f.Section("").NewKey("IMPORT_PATH", "gopkg.in/ini.v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
So(f.Section("").KeyStrings(), ShouldResemble, []string{"NAME", "VERSION", "IMPORT_PATH"})
assert.Equal(t, []string{"NAME", "VERSION", "IMPORT_PATH"}, f.Section("").KeyStrings())
})
}
func TestSection_KeyHash(t *testing.T) {
Convey("Get clone of key hash", t, func() {
t.Run("get clone of key hash", func(t *testing.T) {
f, err := ini.Load([]byte(`
key = one
[log]
@@ -283,10 +285,10 @@ key = two
name = app2
file = b.log
`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
So(f.Section("").Key("key").String(), ShouldEqual, "two")
assert.Equal(t, "two", f.Section("").Key("key").String())
hash := f.Section("log").KeysHash()
relation := map[string]string{
@@ -294,22 +296,22 @@ file = b.log
"file": "b.log",
}
for k, v := range hash {
So(v, ShouldEqual, relation[k])
assert.Equal(t, relation[k], v)
}
})
}
func TestSection_DeleteKey(t *testing.T) {
Convey("Delete a key", t, func() {
t.Run("delete a key", func(t *testing.T) {
f := ini.Empty()
So(f, ShouldNotBeNil)
require.NotNil(t, f)
k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, k)
So(f.Section("").HasKey("NAME"), ShouldBeTrue)
assert.True(t, f.Section("").HasKey("NAME"))
f.Section("").DeleteKey("NAME")
So(f.Section("").HasKey("NAME"), ShouldBeFalse)
assert.False(t, f.Section("").HasKey("NAME"))
})
}
+214 -197
View File
@@ -21,7 +21,8 @@ import (
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/ini.v1"
)
@@ -215,88 +216,88 @@ Cities =
`
func Test_MapToStruct(t *testing.T) {
Convey("Map to struct", t, func() {
Convey("Map file to struct", func() {
t.Run("map to struct", func(t *testing.T) {
t.Run("map file to struct", func(t *testing.T) {
ts := new(testStruct)
So(ini.MapTo(ts, []byte(confDataStruct)), ShouldBeNil)
assert.NoError(t, ini.MapTo(ts, []byte(confDataStruct)))
So(ts.Name, ShouldEqual, "Unknwon")
So(ts.Age, ShouldEqual, 21)
So(ts.Male, ShouldBeTrue)
So(ts.Money, ShouldEqual, 1.25)
So(ts.Unsigned, ShouldEqual, 3)
assert.Equal(t, "Unknwon", ts.Name)
assert.Equal(t, 21, ts.Age)
assert.True(t, ts.Male)
assert.Equal(t, 1.25, ts.Money)
assert.Equal(t, uint(3), ts.Unsigned)
t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
So(err, ShouldBeNil)
So(ts.Born.String(), ShouldEqual, t.String())
ti, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
require.NoError(t, err)
assert.Equal(t, ti.String(), ts.Born.String())
dur, err := time.ParseDuration("2h45m")
So(err, ShouldBeNil)
So(ts.Time.Seconds(), ShouldEqual, dur.Seconds())
require.NoError(t, err)
assert.Equal(t, dur.Seconds(), ts.Time.Seconds())
So(ts.OldVersionTime*time.Second, ShouldEqual, 30*time.Second)
assert.Equal(t, 30*time.Second, ts.OldVersionTime*time.Second)
So(strings.Join(ts.Others.Cities, ","), ShouldEqual, "HangZhou,Boston")
So(ts.Others.Visits[0].String(), ShouldEqual, t.String())
So(fmt.Sprint(ts.Others.Years), ShouldEqual, "[1993 1994]")
So(fmt.Sprint(ts.Others.Numbers), ShouldEqual, "[10010 10086]")
So(fmt.Sprint(ts.Others.Ages), ShouldEqual, "[18 19]")
So(fmt.Sprint(ts.Others.Populations), ShouldEqual, "[12345678 98765432]")
So(fmt.Sprint(ts.Others.Coordinates), ShouldEqual, "[192.168 10.11]")
So(fmt.Sprint(ts.Others.Flags), ShouldEqual, "[true false]")
So(ts.Others.Note, ShouldEqual, "Hello world!")
So(ts.TestEmbeded.GPA, ShouldEqual, 2.8)
assert.Equal(t, "HangZhou,Boston", strings.Join(ts.Others.Cities, ","))
assert.Equal(t, ti.String(), ts.Others.Visits[0].String())
assert.Equal(t, "[1993 1994]", fmt.Sprint(ts.Others.Years))
assert.Equal(t, "[10010 10086]", fmt.Sprint(ts.Others.Numbers))
assert.Equal(t, "[18 19]", fmt.Sprint(ts.Others.Ages))
assert.Equal(t, "[12345678 98765432]", fmt.Sprint(ts.Others.Populations))
assert.Equal(t, "[192.168 10.11]", fmt.Sprint(ts.Others.Coordinates))
assert.Equal(t, "[true false]", fmt.Sprint(ts.Others.Flags))
assert.Equal(t, "Hello world!", ts.Others.Note)
assert.Equal(t, 2.8, ts.TestEmbeded.GPA)
So(strings.Join(ts.OthersPtr.Cities, ","), ShouldEqual, "HangZhou,Boston")
So(ts.OthersPtr.Visits[0].String(), ShouldEqual, t.String())
So(fmt.Sprint(ts.OthersPtr.Years), ShouldEqual, "[1993 1994]")
So(fmt.Sprint(ts.OthersPtr.Numbers), ShouldEqual, "[10010 10086]")
So(fmt.Sprint(ts.OthersPtr.Ages), ShouldEqual, "[18 19]")
So(fmt.Sprint(ts.OthersPtr.Populations), ShouldEqual, "[12345678 98765432]")
So(fmt.Sprint(ts.OthersPtr.Coordinates), ShouldEqual, "[192.168 10.11]")
So(fmt.Sprint(ts.OthersPtr.Flags), ShouldEqual, "[true false]")
So(ts.OthersPtr.Note, ShouldEqual, "Hello world!")
assert.Equal(t, "HangZhou,Boston", strings.Join(ts.OthersPtr.Cities, ","))
assert.Equal(t, ti.String(), ts.OthersPtr.Visits[0].String())
assert.Equal(t, "[1993 1994]", fmt.Sprint(ts.OthersPtr.Years))
assert.Equal(t, "[10010 10086]", fmt.Sprint(ts.OthersPtr.Numbers))
assert.Equal(t, "[18 19]", fmt.Sprint(ts.OthersPtr.Ages))
assert.Equal(t, "[12345678 98765432]", fmt.Sprint(ts.OthersPtr.Populations))
assert.Equal(t, "[192.168 10.11]", fmt.Sprint(ts.OthersPtr.Coordinates))
assert.Equal(t, "[true false]", fmt.Sprint(ts.OthersPtr.Flags))
assert.Equal(t, "Hello world!", ts.OthersPtr.Note)
So(ts.NilPtr, ShouldBeNil)
assert.Nil(t, ts.NilPtr)
So(*ts.BoolPtr, ShouldEqual, false)
So(ts.BoolPtrNil, ShouldEqual, nil)
So(*ts.FloatPtr, ShouldEqual, 0)
So(ts.FloatPtrNil, ShouldEqual, nil)
So(*ts.IntPtr, ShouldEqual, 0)
So(ts.IntPtrNil, ShouldEqual, nil)
So(*ts.UintPtr, ShouldEqual, 0)
So(ts.UintPtrNil, ShouldEqual, nil)
So(*ts.StringPtr, ShouldEqual, "")
So(ts.StringPtrNil, ShouldEqual, nil)
So(*ts.TimePtr, ShouldNotEqual, nil)
So(ts.TimePtrNil, ShouldEqual, nil)
So(*ts.DurationPtr, ShouldEqual, 0)
So(ts.DurationPtrNil, ShouldEqual, nil)
assert.Equal(t, false, *ts.BoolPtr)
assert.Nil(t, ts.BoolPtrNil)
assert.Equal(t, float64(0), *ts.FloatPtr)
assert.Nil(t, ts.FloatPtrNil)
assert.Equal(t, 0, *ts.IntPtr)
assert.Nil(t, ts.IntPtrNil)
assert.Equal(t, uint(0), *ts.UintPtr)
assert.Nil(t, ts.UintPtrNil)
assert.Equal(t, "", *ts.StringPtr)
assert.Nil(t, ts.StringPtrNil)
assert.NotNil(t, *ts.TimePtr)
assert.Nil(t, ts.TimePtrNil)
assert.Equal(t, time.Duration(0), *ts.DurationPtr)
assert.Nil(t, ts.DurationPtrNil)
})
Convey("Map section to struct", func() {
t.Run("map section to struct", func(t *testing.T) {
foobar := new(fooBar)
f, err := ini.Load([]byte(confDataStruct))
So(err, ShouldBeNil)
require.NoError(t, err)
So(f.Section("foo.bar").MapTo(foobar), ShouldBeNil)
So(foobar.Here, ShouldEqual, "there")
So(foobar.When, ShouldEqual, "then")
assert.NoError(t, f.Section("foo.bar").MapTo(foobar))
assert.Equal(t, "there", foobar.Here)
assert.Equal(t, "then", foobar.When)
})
Convey("Map to non-pointer struct", func() {
t.Run("map to non-pointer struct", func(t *testing.T) {
f, err := ini.Load([]byte(confDataStruct))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
So(f.MapTo(testStruct{}), ShouldNotBeNil)
assert.Error(t, f.MapTo(testStruct{}))
})
Convey("Map to unsupported type", func() {
t.Run("map to unsupported type", func(t *testing.T) {
f, err := ini.Load([]byte(confDataStruct))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
f.NameMapper = func(raw string) string {
if raw == "Byte" {
@@ -304,64 +305,64 @@ func Test_MapToStruct(t *testing.T) {
}
return raw
}
So(f.MapTo(&unsupport{}), ShouldNotBeNil)
So(f.MapTo(&unsupport2{}), ShouldNotBeNil)
So(f.MapTo(&unsupport4{}), ShouldNotBeNil)
assert.Error(t, f.MapTo(&unsupport{}))
assert.Error(t, f.MapTo(&unsupport2{}))
assert.Error(t, f.MapTo(&unsupport4{}))
})
Convey("Map to omitempty field", func() {
t.Run("map to omitempty field", func(t *testing.T) {
ts := new(testStruct)
So(ini.MapTo(ts, []byte(confDataStruct)), ShouldBeNil)
assert.NoError(t, ini.MapTo(ts, []byte(confDataStruct)))
So(ts.Omitted, ShouldEqual, true)
assert.Equal(t, true, ts.Omitted)
})
Convey("Map with shadows", func() {
t.Run("map with shadows", func(t *testing.T) {
f, err := ini.LoadSources(ini.LoadOptions{AllowShadows: true}, []byte(confDataStruct))
So(err, ShouldBeNil)
require.NoError(t, err)
ts := new(testStruct)
So(f.MapTo(ts), ShouldBeNil)
assert.NoError(t, f.MapTo(ts))
So(strings.Join(ts.Shadows, " "), ShouldEqual, "1 2 3 4")
So(fmt.Sprintf("%v", ts.ShadowInts), ShouldEqual, "[1 2 3 4]")
assert.Equal(t, "1 2 3 4", strings.Join(ts.Shadows, " "))
assert.Equal(t, "[1 2 3 4]", fmt.Sprintf("%v", ts.ShadowInts))
})
Convey("Map from invalid data source", func() {
So(ini.MapTo(&testStruct{}, "hi"), ShouldNotBeNil)
t.Run("map from invalid data source", func(t *testing.T) {
assert.Error(t, ini.MapTo(&testStruct{}, "hi"))
})
Convey("Map to wrong types and gain default values", func() {
t.Run("map to wrong types and gain default values", func(t *testing.T) {
f, err := ini.Load([]byte(invalidDataConfStruct))
So(err, ShouldBeNil)
require.NoError(t, err)
t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
So(err, ShouldBeNil)
dv := &defaultValue{"Joe", 10, true, nil, 1.25, t, []string{"HangZhou", "Boston"}}
So(f.MapTo(dv), ShouldBeNil)
So(dv.Name, ShouldEqual, "Joe")
So(dv.Age, ShouldEqual, 10)
So(dv.Male, ShouldBeTrue)
So(dv.Money, ShouldEqual, 1.25)
So(dv.Born.String(), ShouldEqual, t.String())
So(strings.Join(dv.Cities, ","), ShouldEqual, "HangZhou,Boston")
ti, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
require.NoError(t, err)
dv := &defaultValue{"Joe", 10, true, nil, 1.25, ti, []string{"HangZhou", "Boston"}}
assert.NoError(t, f.MapTo(dv))
assert.Equal(t, "Joe", dv.Name)
assert.Equal(t, 10, dv.Age)
assert.True(t, dv.Male)
assert.Equal(t, 1.25, dv.Money)
assert.Equal(t, ti.String(), dv.Born.String())
assert.Equal(t, "HangZhou,Boston", strings.Join(dv.Cities, ","))
})
Convey("Map to extended base", func() {
t.Run("map to extended base", func(t *testing.T) {
f, err := ini.Load([]byte(confDataStruct))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, f)
te := testExtend{}
So(f.Section("extended").MapTo(&te), ShouldBeNil)
So(te.Base, ShouldBeTrue)
So(te.Extend, ShouldBeTrue)
assert.NoError(t, f.Section("extended").MapTo(&te))
assert.True(t, te.Base)
assert.True(t, te.Extend)
})
})
Convey("Map to struct in strict mode", t, func() {
t.Run("map to struct in strict mode", func(t *testing.T) {
f, err := ini.Load([]byte(`
name=bruce
age=a30`))
So(err, ShouldBeNil)
require.NoError(t, err)
type Strict struct {
Name string `ini:"name"`
@@ -369,76 +370,76 @@ age=a30`))
}
s := new(Strict)
So(f.Section("").StrictMapTo(s), ShouldNotBeNil)
assert.Error(t, f.Section("").StrictMapTo(s))
})
Convey("Map slice in strict mode", t, func() {
t.Run("map slice in strict mode", func(t *testing.T) {
f, err := ini.Load([]byte(`
names=alice, bruce`))
So(err, ShouldBeNil)
require.NoError(t, err)
type Strict struct {
Names []string `ini:"names"`
}
s := new(Strict)
So(f.Section("").StrictMapTo(s), ShouldBeNil)
So(fmt.Sprint(s.Names), ShouldEqual, "[alice bruce]")
assert.NoError(t, f.Section("").StrictMapTo(s))
assert.Equal(t, "[alice bruce]", fmt.Sprint(s.Names))
})
}
func Test_MapToStructNonUniqueSections(t *testing.T) {
Convey("Map to struct non unique", t, func() {
Convey("Map file to struct non unique", func() {
t.Run("map to struct non unique", func(t *testing.T) {
t.Run("map file to struct non unique", func(t *testing.T) {
f, err := ini.LoadSources(ini.LoadOptions{AllowNonUniqueSections: true}, []byte(confNonUniqueSectionDataStruct))
So(err, ShouldBeNil)
require.NoError(t, err)
ts := new(testNonUniqueSectionsStruct)
So(f.MapTo(ts), ShouldBeNil)
assert.NoError(t, f.MapTo(ts))
So(ts.Interface.Address, ShouldEqual, "10.2.0.1/24")
So(ts.Interface.ListenPort, ShouldEqual, 34777)
So(ts.Interface.PrivateKey, ShouldEqual, "privServerKey")
assert.Equal(t, "10.2.0.1/24", ts.Interface.Address)
assert.Equal(t, 34777, ts.Interface.ListenPort)
assert.Equal(t, "privServerKey", ts.Interface.PrivateKey)
So(ts.Peer[0].PublicKey, ShouldEqual, "pubClientKey")
So(ts.Peer[0].PresharedKey, ShouldEqual, "psKey")
So(ts.Peer[0].AllowedIPs[0], ShouldEqual, "10.2.0.2/32")
So(ts.Peer[0].AllowedIPs[1], ShouldEqual, "fd00:2::2/128")
assert.Equal(t, "pubClientKey", ts.Peer[0].PublicKey)
assert.Equal(t, "psKey", ts.Peer[0].PresharedKey)
assert.Equal(t, "10.2.0.2/32", ts.Peer[0].AllowedIPs[0])
assert.Equal(t, "fd00:2::2/128", ts.Peer[0].AllowedIPs[1])
So(ts.Peer[1].PublicKey, ShouldEqual, "pubClientKey2")
So(ts.Peer[1].PresharedKey, ShouldEqual, "psKey2")
So(ts.Peer[1].AllowedIPs[0], ShouldEqual, "10.2.0.3/32")
So(ts.Peer[1].AllowedIPs[1], ShouldEqual, "fd00:2::3/128")
assert.Equal(t, "pubClientKey2", ts.Peer[1].PublicKey)
assert.Equal(t, "psKey2", ts.Peer[1].PresharedKey)
assert.Equal(t, "10.2.0.3/32", ts.Peer[1].AllowedIPs[0])
assert.Equal(t, "fd00:2::3/128", ts.Peer[1].AllowedIPs[1])
})
Convey("Map non unique section to struct", func() {
t.Run("map non unique section to struct", func(t *testing.T) {
newPeer := new(testPeer)
newPeerSlice := make([]testPeer, 0)
f, err := ini.LoadSources(ini.LoadOptions{AllowNonUniqueSections: true}, []byte(confNonUniqueSectionDataStruct))
So(err, ShouldBeNil)
require.NoError(t, err)
// try only first one
So(f.Section("Peer").MapTo(newPeer), ShouldBeNil)
So(newPeer.PublicKey, ShouldEqual, "pubClientKey")
So(newPeer.PresharedKey, ShouldEqual, "psKey")
So(newPeer.AllowedIPs[0], ShouldEqual, "10.2.0.2/32")
So(newPeer.AllowedIPs[1], ShouldEqual, "fd00:2::2/128")
assert.NoError(t, f.Section("Peer").MapTo(newPeer))
assert.Equal(t, "pubClientKey", newPeer.PublicKey)
assert.Equal(t, "psKey", newPeer.PresharedKey)
assert.Equal(t, "10.2.0.2/32", newPeer.AllowedIPs[0])
assert.Equal(t, "fd00:2::2/128", newPeer.AllowedIPs[1])
// try all
So(f.Section("Peer").MapTo(&newPeerSlice), ShouldBeNil)
So(newPeerSlice[0].PublicKey, ShouldEqual, "pubClientKey")
So(newPeerSlice[0].PresharedKey, ShouldEqual, "psKey")
So(newPeerSlice[0].AllowedIPs[0], ShouldEqual, "10.2.0.2/32")
So(newPeerSlice[0].AllowedIPs[1], ShouldEqual, "fd00:2::2/128")
assert.NoError(t, f.Section("Peer").MapTo(&newPeerSlice))
assert.Equal(t, "pubClientKey", newPeerSlice[0].PublicKey)
assert.Equal(t, "psKey", newPeerSlice[0].PresharedKey)
assert.Equal(t, "10.2.0.2/32", newPeerSlice[0].AllowedIPs[0])
assert.Equal(t, "fd00:2::2/128", newPeerSlice[0].AllowedIPs[1])
So(newPeerSlice[1].PublicKey, ShouldEqual, "pubClientKey2")
So(newPeerSlice[1].PresharedKey, ShouldEqual, "psKey2")
So(newPeerSlice[1].AllowedIPs[0], ShouldEqual, "10.2.0.3/32")
So(newPeerSlice[1].AllowedIPs[1], ShouldEqual, "fd00:2::3/128")
assert.Equal(t, "pubClientKey2", newPeerSlice[1].PublicKey)
assert.Equal(t, "psKey2", newPeerSlice[1].PresharedKey)
assert.Equal(t, "10.2.0.3/32", newPeerSlice[1].AllowedIPs[0])
assert.Equal(t, "fd00:2::3/128", newPeerSlice[1].AllowedIPs[1])
})
Convey("Map non unique sections with subsections to struct", func() {
t.Run("map non unique sections with subsections to struct", func(t *testing.T) {
iniFile, err := ini.LoadSources(ini.LoadOptions{AllowNonUniqueSections: true}, strings.NewReader(`
[Section]
FieldInSubSection = 1
@@ -450,7 +451,7 @@ FieldInSubSection = 4
FieldInSubSection2 = 5
FieldInSection = 6
`))
So(err, ShouldBeNil)
require.NoError(t, err)
type SubSection struct {
FieldInSubSection string `ini:"FieldInSubSection"`
@@ -471,21 +472,21 @@ FieldInSection = 6
f := new(File)
err = iniFile.MapTo(f)
So(err, ShouldBeNil)
require.NoError(t, err)
So(f.Sections[0].FieldInSubSection, ShouldEqual, "1")
So(f.Sections[0].FieldInSubSection2, ShouldEqual, "2")
So(f.Sections[0].FieldInSection, ShouldEqual, "3")
assert.Equal(t, "1", f.Sections[0].FieldInSubSection)
assert.Equal(t, "2", f.Sections[0].FieldInSubSection2)
assert.Equal(t, "3", f.Sections[0].FieldInSection)
So(f.Sections[1].FieldInSubSection, ShouldEqual, "4")
So(f.Sections[1].FieldInSubSection2, ShouldEqual, "5")
So(f.Sections[1].FieldInSection, ShouldEqual, "6")
assert.Equal(t, "4", f.Sections[1].FieldInSubSection)
assert.Equal(t, "5", f.Sections[1].FieldInSubSection2)
assert.Equal(t, "6", f.Sections[1].FieldInSection)
})
})
}
func Test_ReflectFromStruct(t *testing.T) {
Convey("Reflect from struct", t, func() {
t.Run("reflect from struct", func(t *testing.T) {
type Embeded struct {
Dates []time.Time `delim:"|" comment:"Time data"`
Places []string
@@ -510,11 +511,11 @@ func Test_ReflectFromStruct(t *testing.T) {
*Embeded `ini:"infos" comment:"Embeded section"`
}
t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
So(err, ShouldBeNil)
a := &Author{"Unknwon", true, nil, 21, 100, 2.8, t, "", "ignored",
ti, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
require.NoError(t, err)
a := &Author{"Unknwon", true, nil, 21, 100, 2.8, ti, "", "ignored",
&Embeded{
[]time.Time{t, t},
[]time.Time{ti, ti},
[]string{"HangZhou", "Boston"},
[]int{1993, 1994},
[]int64{10010, 10086},
@@ -525,12 +526,12 @@ func Test_ReflectFromStruct(t *testing.T) {
[]int{},
}}
cfg := ini.Empty()
So(ini.ReflectFrom(cfg, a), ShouldBeNil)
assert.NoError(t, ini.ReflectFrom(cfg, a))
var buf bytes.Buffer
_, err = cfg.WriteTo(&buf)
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, `NAME = Unknwon
require.NoError(t, err)
assert.Equal(t, `NAME = Unknwon
Male = true
Optional =
; Author's age
@@ -552,13 +553,15 @@ Coordinates = 192.168,10.11
Flags = true,false
None =
`)
`,
buf.String(),
)
Convey("Reflect from non-point struct", func() {
So(ini.ReflectFrom(cfg, Author{}), ShouldNotBeNil)
t.Run("reflect from non-point struct", func(t *testing.T) {
assert.Error(t, ini.ReflectFrom(cfg, Author{}))
})
Convey("Reflect from struct with omitempty", func() {
t.Run("reflect from struct with omitempty", func(t *testing.T) {
cfg := ini.Empty()
type SpecialStruct struct {
FirstName string `ini:"first_name"`
@@ -580,18 +583,20 @@ None =
NotEmpty: 9,
}
So(ini.ReflectFrom(cfg, special), ShouldBeNil)
assert.NoError(t, ini.ReflectFrom(cfg, special))
var buf bytes.Buffer
_, err = cfg.WriteTo(&buf)
So(buf.String(), ShouldEqual, `first_name = John
assert.Equal(t, `first_name = John
last_name = Doe
omitempty = 9
`)
`,
buf.String(),
)
})
Convey("Reflect from struct with non-anonymous structure pointer", func() {
t.Run("reflect from struct with non-anonymous structure pointer", func(t *testing.T) {
cfg := ini.Empty()
type Rpc struct {
Enable bool `ini:"enable"`
@@ -611,23 +616,25 @@ omitempty = 9
Name: "name",
},
}
So(cfg.ReflectFrom(config), ShouldBeNil)
assert.NoError(t, cfg.ReflectFrom(config))
var buf bytes.Buffer
_, err = cfg.WriteTo(&buf)
So(buf.String(), ShouldEqual, `[rpc]
assert.Equal(t, `[rpc]
enable = true
type = type
addr = address
name = name
`)
`,
buf.String(),
)
})
})
}
func Test_ReflectFromStructNonUniqueSections(t *testing.T) {
Convey("Reflect from struct with non unique sections", t, func() {
t.Run("reflect from struct with non unique sections", func(t *testing.T) {
nonUnique := &testNonUniqueSectionsStruct{
Interface: testInterface{
Address: "10.2.0.1/24",
@@ -652,12 +659,12 @@ func Test_ReflectFromStructNonUniqueSections(t *testing.T) {
AllowNonUniqueSections: true,
})
So(ini.ReflectFrom(cfg, nonUnique), ShouldBeNil)
assert.NoError(t, ini.ReflectFrom(cfg, nonUnique))
var buf bytes.Buffer
_, err := cfg.WriteTo(&buf)
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, confNonUniqueSectionDataStruct)
require.NoError(t, err)
assert.Equal(t, confNonUniqueSectionDataStruct, buf.String())
// note: using ReflectFrom from should overwrite the existing sections
err = cfg.Section("Peer").ReflectFrom([]*testPeer{
@@ -673,12 +680,12 @@ func Test_ReflectFromStructNonUniqueSections(t *testing.T) {
},
})
So(err, ShouldBeNil)
require.NoError(t, err)
buf = bytes.Buffer{}
_, err = cfg.WriteTo(&buf)
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, `[Interface]
require.NoError(t, err)
assert.Equal(t, `[Interface]
Address = 10.2.0.1/24
ListenPort = 34777
PrivateKey = privServerKey
@@ -693,7 +700,9 @@ PublicKey = pubClientKey4
PresharedKey = psKey4
AllowedIPs = 10.2.0.5/32,fd00:2::5/128
`)
`,
buf.String(),
)
// note: using ReflectFrom from should overwrite the existing sections
err = cfg.Section("Peer").ReflectFrom(&testPeer{
@@ -702,12 +711,12 @@ AllowedIPs = 10.2.0.5/32,fd00:2::5/128
AllowedIPs: []string{"10.2.0.6/32,fd00:2::6/128"},
})
So(err, ShouldBeNil)
require.NoError(t, err)
buf = bytes.Buffer{}
_, err = cfg.WriteTo(&buf)
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, `[Interface]
require.NoError(t, err)
assert.Equal(t, `[Interface]
Address = 10.2.0.1/24
ListenPort = 34777
PrivateKey = privServerKey
@@ -717,13 +726,15 @@ PublicKey = pubClientKey5
PresharedKey = psKey5
AllowedIPs = 10.2.0.6/32,fd00:2::6/128
`)
`,
buf.String(),
)
})
}
// Inspired by https://github.com/go-ini/ini/issues/196
func TestMapToAndReflectFromStructWithShadows(t *testing.T) {
Convey("Map to struct and then reflect with shadows should generate original config content", t, func() {
t.Run("map to struct and then reflect with shadows should generate original config content", func(t *testing.T) {
type include struct {
Paths []string `ini:"path,omitempty,allowshadow"`
}
@@ -734,26 +745,28 @@ func TestMapToAndReflectFromStructWithShadows(t *testing.T) {
[include]
path = /tmp/gpm-profiles/test5.profile
path = /tmp/gpm-profiles/test1.profile`))
So(err, ShouldBeNil)
require.NoError(t, err)
sec := cfg.Section("include")
inc := new(include)
err = sec.MapTo(inc)
So(err, ShouldBeNil)
require.NoError(t, err)
err = sec.ReflectFrom(inc)
So(err, ShouldBeNil)
require.NoError(t, err)
var buf bytes.Buffer
_, err = cfg.WriteTo(&buf)
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, `[include]
require.NoError(t, err)
assert.Equal(t, `[include]
path = /tmp/gpm-profiles/test5.profile
path = /tmp/gpm-profiles/test1.profile
`)
`,
buf.String(),
)
Convey("Reflect from struct with shadows", func() {
t.Run("reflect from struct with shadows", func(t *testing.T) {
cfg := ini.Empty(ini.LoadOptions{
AllowShadows: true,
})
@@ -787,12 +800,12 @@ path = /tmp/gpm-profiles/test1.profile
None: []int{},
}
So(ini.ReflectFrom(cfg, shadow), ShouldBeNil)
assert.NoError(t, ini.ReflectFrom(cfg, shadow))
var buf bytes.Buffer
_, err := cfg.WriteTo(&buf)
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, `sa = s1
require.NoError(t, err)
assert.Equal(t, `sa = s1
sa = s2
allowshadow = s3
allowshadow = s4
@@ -813,7 +826,9 @@ Flags = true
Flags = false
None =
`)
`,
buf.String(),
)
})
})
}
@@ -823,17 +838,17 @@ type testMapper struct {
}
func Test_NameGetter(t *testing.T) {
Convey("Test name mappers", t, func() {
So(ini.MapToWithMapper(&testMapper{}, ini.TitleUnderscore, []byte("packag_name=ini")), ShouldBeNil)
t.Run("test name mappers", func(t *testing.T) {
assert.NoError(t, ini.MapToWithMapper(&testMapper{}, ini.TitleUnderscore, []byte("packag_name=ini")))
cfg, err := ini.Load([]byte("PACKAGE_NAME=ini"))
So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, cfg)
cfg.NameMapper = ini.SnackCase
tg := new(testMapper)
So(cfg.MapTo(tg), ShouldBeNil)
So(tg.PackageName, ShouldEqual, "ini")
assert.NoError(t, cfg.MapTo(tg))
assert.Equal(t, "ini", tg.PackageName)
})
}
@@ -842,13 +857,13 @@ type testDurationStruct struct {
}
func Test_Duration(t *testing.T) {
Convey("Duration less than 16m50s", t, func() {
t.Run("duration less than 16m50s", func(t *testing.T) {
ds := new(testDurationStruct)
So(ini.MapTo(ds, []byte("Duration=16m49s")), ShouldBeNil)
assert.NoError(t, ini.MapTo(ds, []byte("Duration=16m49s")))
dur, err := time.ParseDuration("16m49s")
So(err, ShouldBeNil)
So(ds.Duration.Seconds(), ShouldEqual, dur.Seconds())
require.NoError(t, err)
assert.Equal(t, dur.Seconds(), ds.Duration.Seconds())
})
}
@@ -868,7 +883,7 @@ func (es Employers) ReflectINIStruct(f *ini.File) error {
// Inspired by https://github.com/go-ini/ini/issues/199
func Test_StructReflector(t *testing.T) {
Convey("Reflect with StructReflector interface", t, func() {
t.Run("reflect with StructReflector interface", func(t *testing.T) {
p := &struct {
FirstName string
Employer Employers
@@ -887,13 +902,13 @@ func Test_StructReflector(t *testing.T) {
}
f := ini.Empty()
So(f.ReflectFrom(p), ShouldBeNil)
assert.NoError(t, f.ReflectFrom(p))
var buf bytes.Buffer
_, err := f.WriteTo(&buf)
So(err, ShouldBeNil)
require.NoError(t, err)
So(buf.String(), ShouldEqual, `FirstName = Andrew
assert.Equal(t, `FirstName = Andrew
[Employer "VMware"]
Title = Staff II Engineer
@@ -901,6 +916,8 @@ Title = Staff II Engineer
[Employer "EMC"]
Title = Consultant Engineer
`)
`,
buf.String(),
)
})
}