file_test.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. // Copyright 2017 Unknwon
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License"): you may
  4. // not use this file except in compliance with the License. You may obtain
  5. // a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  11. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  12. // License for the specific language governing permissions and limitations
  13. // under the License.
  14. package ini_test
  15. import (
  16. "bytes"
  17. "io/ioutil"
  18. "testing"
  19. . "github.com/smartystreets/goconvey/convey"
  20. "gopkg.in/ini.v1"
  21. )
  22. func TestEmpty(t *testing.T) {
  23. Convey("Create an empty object", t, func() {
  24. f := ini.Empty()
  25. So(f, ShouldNotBeNil)
  26. // Should only have the default section
  27. So(len(f.Sections()), ShouldEqual, 1)
  28. // Default section should not contain any key
  29. So(len(f.Section("").Keys()), ShouldBeZeroValue)
  30. })
  31. }
  32. func TestFile_NewSection(t *testing.T) {
  33. Convey("Create a new section", t, func() {
  34. f := ini.Empty()
  35. So(f, ShouldNotBeNil)
  36. sec, err := f.NewSection("author")
  37. So(err, ShouldBeNil)
  38. So(sec, ShouldNotBeNil)
  39. So(sec.Name(), ShouldEqual, "author")
  40. So(f.SectionStrings(), ShouldResemble, []string{ini.DefaultSection, "author"})
  41. Convey("With duplicated name", func() {
  42. sec, err := f.NewSection("author")
  43. So(err, ShouldBeNil)
  44. So(sec, ShouldNotBeNil)
  45. // Does nothing if section already exists
  46. So(f.SectionStrings(), ShouldResemble, []string{ini.DefaultSection, "author"})
  47. })
  48. Convey("With empty string", func() {
  49. _, err := f.NewSection("")
  50. So(err, ShouldNotBeNil)
  51. })
  52. })
  53. }
  54. func TestFile_NewRawSection(t *testing.T) {
  55. Convey("Create a new raw section", t, func() {
  56. f := ini.Empty()
  57. So(f, ShouldNotBeNil)
  58. sec, err := f.NewRawSection("comments", `1111111111111111111000000000000000001110000
  59. 111111111111111111100000000000111000000000`)
  60. So(err, ShouldBeNil)
  61. So(sec, ShouldNotBeNil)
  62. So(sec.Name(), ShouldEqual, "comments")
  63. So(f.SectionStrings(), ShouldResemble, []string{ini.DefaultSection, "comments"})
  64. So(f.Section("comments").Body(), ShouldEqual, `1111111111111111111000000000000000001110000
  65. 111111111111111111100000000000111000000000`)
  66. Convey("With duplicated name", func() {
  67. sec, err := f.NewRawSection("comments", `1111111111111111111000000000000000001110000`)
  68. So(err, ShouldBeNil)
  69. So(sec, ShouldNotBeNil)
  70. So(f.SectionStrings(), ShouldResemble, []string{ini.DefaultSection, "comments"})
  71. // Overwrite previous existed section
  72. So(f.Section("comments").Body(), ShouldEqual, `1111111111111111111000000000000000001110000`)
  73. })
  74. Convey("With empty string", func() {
  75. _, err := f.NewRawSection("", "")
  76. So(err, ShouldNotBeNil)
  77. })
  78. })
  79. }
  80. func TestFile_NewSections(t *testing.T) {
  81. Convey("Create new sections", t, func() {
  82. f := ini.Empty()
  83. So(f, ShouldNotBeNil)
  84. So(f.NewSections("package", "author"), ShouldBeNil)
  85. So(f.SectionStrings(), ShouldResemble, []string{ini.DefaultSection, "package", "author"})
  86. Convey("With duplicated name", func() {
  87. So(f.NewSections("author", "features"), ShouldBeNil)
  88. // Ignore section already exists
  89. So(f.SectionStrings(), ShouldResemble, []string{ini.DefaultSection, "package", "author", "features"})
  90. })
  91. Convey("With empty string", func() {
  92. So(f.NewSections("", ""), ShouldNotBeNil)
  93. })
  94. })
  95. }
  96. func TestFile_GetSection(t *testing.T) {
  97. Convey("Get a section", t, func() {
  98. f, err := ini.Load(fullConf)
  99. So(err, ShouldBeNil)
  100. So(f, ShouldNotBeNil)
  101. sec, err := f.GetSection("author")
  102. So(err, ShouldBeNil)
  103. So(sec, ShouldNotBeNil)
  104. So(sec.Name(), ShouldEqual, "author")
  105. Convey("Section not exists", func() {
  106. _, err := f.GetSection("404")
  107. So(err, ShouldNotBeNil)
  108. })
  109. })
  110. }
  111. func TestFile_Section(t *testing.T) {
  112. Convey("Get a section", t, func() {
  113. f, err := ini.Load(fullConf)
  114. So(err, ShouldBeNil)
  115. So(f, ShouldNotBeNil)
  116. sec := f.Section("author")
  117. So(sec, ShouldNotBeNil)
  118. So(sec.Name(), ShouldEqual, "author")
  119. Convey("Section not exists", func() {
  120. sec := f.Section("404")
  121. So(sec, ShouldNotBeNil)
  122. So(sec.Name(), ShouldEqual, "404")
  123. })
  124. })
  125. Convey("Get default section in lower case with insensitive load", t, func() {
  126. f, err := ini.InsensitiveLoad([]byte(`
  127. [default]
  128. NAME = ini
  129. VERSION = v1`))
  130. So(err, ShouldBeNil)
  131. So(f, ShouldNotBeNil)
  132. So(f.Section("").Key("name").String(), ShouldEqual, "ini")
  133. So(f.Section("").Key("version").String(), ShouldEqual, "v1")
  134. })
  135. }
  136. func TestFile_Sections(t *testing.T) {
  137. Convey("Get all sections", t, func() {
  138. f, err := ini.Load(fullConf)
  139. So(err, ShouldBeNil)
  140. So(f, ShouldNotBeNil)
  141. secs := f.Sections()
  142. names := []string{ini.DefaultSection, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "string escapes", "advance"}
  143. So(len(secs), ShouldEqual, len(names))
  144. for i, name := range names {
  145. So(secs[i].Name(), ShouldEqual, name)
  146. }
  147. })
  148. }
  149. func TestFile_ChildSections(t *testing.T) {
  150. Convey("Get child sections by parent name", t, func() {
  151. f, err := ini.Load([]byte(`
  152. [node]
  153. [node.biz1]
  154. [node.biz2]
  155. [node.biz3]
  156. [node.bizN]
  157. `))
  158. So(err, ShouldBeNil)
  159. So(f, ShouldNotBeNil)
  160. children := f.ChildSections("node")
  161. names := []string{"node.biz1", "node.biz2", "node.biz3", "node.bizN"}
  162. So(len(children), ShouldEqual, len(names))
  163. for i, name := range names {
  164. So(children[i].Name(), ShouldEqual, name)
  165. }
  166. })
  167. }
  168. func TestFile_SectionStrings(t *testing.T) {
  169. Convey("Get all section names", t, func() {
  170. f, err := ini.Load(fullConf)
  171. So(err, ShouldBeNil)
  172. So(f, ShouldNotBeNil)
  173. So(f.SectionStrings(), ShouldResemble, []string{ini.DefaultSection, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "string escapes", "advance"})
  174. })
  175. }
  176. func TestFile_DeleteSection(t *testing.T) {
  177. Convey("Delete a section", t, func() {
  178. f := ini.Empty()
  179. So(f, ShouldNotBeNil)
  180. f.NewSections("author", "package", "features")
  181. f.DeleteSection("features")
  182. f.DeleteSection("")
  183. So(f.SectionStrings(), ShouldResemble, []string{"author", "package"})
  184. })
  185. }
  186. func TestFile_Append(t *testing.T) {
  187. Convey("Append a data source", t, func() {
  188. f := ini.Empty()
  189. So(f, ShouldNotBeNil)
  190. So(f.Append(minimalConf, []byte(`
  191. [author]
  192. NAME = Unknwon`)), ShouldBeNil)
  193. Convey("With bad input", func() {
  194. So(f.Append(123), ShouldNotBeNil)
  195. So(f.Append(minimalConf, 123), ShouldNotBeNil)
  196. })
  197. })
  198. }
  199. func TestFile_WriteTo(t *testing.T) {
  200. Convey("Write content to somewhere", t, func() {
  201. f, err := ini.Load(fullConf)
  202. So(err, ShouldBeNil)
  203. So(f, ShouldNotBeNil)
  204. f.Section("author").Comment = `Information about package author
  205. # Bio can be written in multiple lines.`
  206. f.Section("author").Key("NAME").Comment = "This is author name"
  207. f.Section("note").NewBooleanKey("boolean_key")
  208. f.Section("note").NewKey("more", "notes")
  209. var buf bytes.Buffer
  210. _, err = f.WriteTo(&buf)
  211. So(err, ShouldBeNil)
  212. golden := "testdata/TestFile_WriteTo.golden"
  213. if *update {
  214. ioutil.WriteFile(golden, buf.Bytes(), 0644)
  215. }
  216. expected, err := ioutil.ReadFile(golden)
  217. So(err, ShouldBeNil)
  218. So(buf.String(), ShouldEqual, string(expected))
  219. })
  220. Convey("Support multiline comments", t, func() {
  221. f, err := ini.Load([]byte(`
  222. #
  223. # general.domain
  224. #
  225. # Domain name of XX system.
  226. domain = mydomain.com
  227. `))
  228. So(err, ShouldBeNil)
  229. f.Section("").Key("test").Comment = "Multiline\nComment"
  230. var buf bytes.Buffer
  231. _, err = f.WriteTo(&buf)
  232. So(err, ShouldBeNil)
  233. So(buf.String(), ShouldEqual, `#
  234. # general.domain
  235. #
  236. # Domain name of XX system.
  237. domain = mydomain.com
  238. ; Multiline
  239. ; Comment
  240. test =
  241. `)
  242. })
  243. }
  244. func TestFile_SaveTo(t *testing.T) {
  245. Convey("Write content to somewhere", t, func() {
  246. f, err := ini.Load(fullConf)
  247. So(err, ShouldBeNil)
  248. So(f, ShouldNotBeNil)
  249. So(f.SaveTo("testdata/conf_out.ini"), ShouldBeNil)
  250. So(f.SaveToIndent("testdata/conf_out.ini", "\t"), ShouldBeNil)
  251. })
  252. }
  253. // Inspired by https://github.com/go-ini/ini/issues/207
  254. func TestReloadAfterShadowLoad(t *testing.T) {
  255. Convey("Reload file after ShadowLoad", t, func() {
  256. f, err := ini.ShadowLoad([]byte(`
  257. [slice]
  258. v = 1
  259. v = 2
  260. v = 3
  261. `))
  262. So(err, ShouldBeNil)
  263. So(f, ShouldNotBeNil)
  264. So(f.Section("slice").Key("v").ValueWithShadows(), ShouldResemble, []string{"1", "2", "3"})
  265. So(f.Reload(), ShouldBeNil)
  266. So(f.Section("slice").Key("v").ValueWithShadows(), ShouldResemble, []string{"1", "2", "3"})
  267. })
  268. }