key_test.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. // Copyright 2014 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
  15. import (
  16. "fmt"
  17. "strings"
  18. "testing"
  19. "time"
  20. . "github.com/smartystreets/goconvey/convey"
  21. )
  22. func Test_Key(t *testing.T) {
  23. Convey("Test getting and setting values", t, func() {
  24. cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini")
  25. So(err, ShouldBeNil)
  26. So(cfg, ShouldNotBeNil)
  27. Convey("Get values in default section", func() {
  28. sec := cfg.Section("")
  29. So(sec, ShouldNotBeNil)
  30. So(sec.Key("NAME").Value(), ShouldEqual, "ini")
  31. So(sec.Key("NAME").String(), ShouldEqual, "ini")
  32. So(sec.Key("NAME").Validate(func(in string) string {
  33. return in
  34. }), ShouldEqual, "ini")
  35. So(sec.Key("NAME").Comment, ShouldEqual, "; Package name")
  36. So(sec.Key("IMPORT_PATH").String(), ShouldEqual, "gopkg.in/ini.v1")
  37. })
  38. Convey("Get values in non-default section", func() {
  39. sec := cfg.Section("author")
  40. So(sec, ShouldNotBeNil)
  41. So(sec.Key("NAME").String(), ShouldEqual, "Unknwon")
  42. So(sec.Key("GITHUB").String(), ShouldEqual, "https://github.com/Unknwon")
  43. sec = cfg.Section("package")
  44. So(sec, ShouldNotBeNil)
  45. So(sec.Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
  46. })
  47. Convey("Get auto-increment key names", func() {
  48. keys := cfg.Section("features").Keys()
  49. for i, k := range keys {
  50. So(k.Name(), ShouldEqual, fmt.Sprintf("#%d", i+1))
  51. }
  52. })
  53. Convey("Get parent-keys that are available to the child section", func() {
  54. parentKeys := cfg.Section("package.sub").ParentKeys()
  55. for _, k := range parentKeys {
  56. So(k.Name(), ShouldEqual, "CLONE_URL")
  57. }
  58. })
  59. Convey("Get overwrite value", func() {
  60. So(cfg.Section("author").Key("E-MAIL").String(), ShouldEqual, "u@gogs.io")
  61. })
  62. Convey("Get sections", func() {
  63. sections := cfg.Sections()
  64. for i, name := range []string{DEFAULT_SECTION, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "advance"} {
  65. So(sections[i].Name(), ShouldEqual, name)
  66. }
  67. })
  68. Convey("Get parent section value", func() {
  69. So(cfg.Section("package.sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
  70. So(cfg.Section("package.fake.sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
  71. })
  72. Convey("Get multiple line value", func() {
  73. So(cfg.Section("author").Key("BIO").String(), ShouldEqual, "Gopher.\nCoding addict.\nGood man.\n")
  74. })
  75. Convey("Get values with type", func() {
  76. sec := cfg.Section("types")
  77. v1, err := sec.Key("BOOL").Bool()
  78. So(err, ShouldBeNil)
  79. So(v1, ShouldBeTrue)
  80. v1, err = sec.Key("BOOL_FALSE").Bool()
  81. So(err, ShouldBeNil)
  82. So(v1, ShouldBeFalse)
  83. v2, err := sec.Key("FLOAT64").Float64()
  84. So(err, ShouldBeNil)
  85. So(v2, ShouldEqual, 1.25)
  86. v3, err := sec.Key("INT").Int()
  87. So(err, ShouldBeNil)
  88. So(v3, ShouldEqual, 10)
  89. v4, err := sec.Key("INT").Int64()
  90. So(err, ShouldBeNil)
  91. So(v4, ShouldEqual, 10)
  92. v5, err := sec.Key("UINT").Uint()
  93. So(err, ShouldBeNil)
  94. So(v5, ShouldEqual, 3)
  95. v6, err := sec.Key("UINT").Uint64()
  96. So(err, ShouldBeNil)
  97. So(v6, ShouldEqual, 3)
  98. t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
  99. So(err, ShouldBeNil)
  100. v7, err := sec.Key("TIME").Time()
  101. So(err, ShouldBeNil)
  102. So(v7.String(), ShouldEqual, t.String())
  103. Convey("Must get values with type", func() {
  104. So(sec.Key("STRING").MustString("404"), ShouldEqual, "str")
  105. So(sec.Key("BOOL").MustBool(), ShouldBeTrue)
  106. So(sec.Key("FLOAT64").MustFloat64(), ShouldEqual, 1.25)
  107. So(sec.Key("INT").MustInt(), ShouldEqual, 10)
  108. So(sec.Key("INT").MustInt64(), ShouldEqual, 10)
  109. So(sec.Key("UINT").MustUint(), ShouldEqual, 3)
  110. So(sec.Key("UINT").MustUint64(), ShouldEqual, 3)
  111. So(sec.Key("TIME").MustTime().String(), ShouldEqual, t.String())
  112. dur, err := time.ParseDuration("2h45m")
  113. So(err, ShouldBeNil)
  114. So(sec.Key("DURATION").MustDuration().Seconds(), ShouldEqual, dur.Seconds())
  115. Convey("Must get values with default value", func() {
  116. So(sec.Key("STRING_404").MustString("404"), ShouldEqual, "404")
  117. So(sec.Key("BOOL_404").MustBool(true), ShouldBeTrue)
  118. So(sec.Key("FLOAT64_404").MustFloat64(2.5), ShouldEqual, 2.5)
  119. So(sec.Key("INT_404").MustInt(15), ShouldEqual, 15)
  120. So(sec.Key("INT64_404").MustInt64(15), ShouldEqual, 15)
  121. So(sec.Key("UINT_404").MustUint(6), ShouldEqual, 6)
  122. So(sec.Key("UINT64_404").MustUint64(6), ShouldEqual, 6)
  123. t, err := time.Parse(time.RFC3339, "2014-01-01T20:17:05Z")
  124. So(err, ShouldBeNil)
  125. So(sec.Key("TIME_404").MustTime(t).String(), ShouldEqual, t.String())
  126. So(sec.Key("DURATION_404").MustDuration(dur).Seconds(), ShouldEqual, dur.Seconds())
  127. Convey("Must should set default as key value", func() {
  128. So(sec.Key("STRING_404").String(), ShouldEqual, "404")
  129. So(sec.Key("BOOL_404").String(), ShouldEqual, "true")
  130. So(sec.Key("FLOAT64_404").String(), ShouldEqual, "2.5")
  131. So(sec.Key("INT_404").String(), ShouldEqual, "15")
  132. So(sec.Key("INT64_404").String(), ShouldEqual, "15")
  133. So(sec.Key("UINT_404").String(), ShouldEqual, "6")
  134. So(sec.Key("UINT64_404").String(), ShouldEqual, "6")
  135. So(sec.Key("TIME_404").String(), ShouldEqual, "2014-01-01T20:17:05Z")
  136. So(sec.Key("DURATION_404").String(), ShouldEqual, "2h45m0s")
  137. })
  138. })
  139. })
  140. })
  141. Convey("Get value with candidates", func() {
  142. sec := cfg.Section("types")
  143. So(sec.Key("STRING").In("", []string{"str", "arr", "types"}), ShouldEqual, "str")
  144. So(sec.Key("FLOAT64").InFloat64(0, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25)
  145. So(sec.Key("INT").InInt(0, []int{10, 20, 30}), ShouldEqual, 10)
  146. So(sec.Key("INT").InInt64(0, []int64{10, 20, 30}), ShouldEqual, 10)
  147. So(sec.Key("UINT").InUint(0, []uint{3, 6, 9}), ShouldEqual, 3)
  148. So(sec.Key("UINT").InUint64(0, []uint64{3, 6, 9}), ShouldEqual, 3)
  149. zt, err := time.Parse(time.RFC3339, "0001-01-01T01:00:00Z")
  150. So(err, ShouldBeNil)
  151. t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
  152. So(err, ShouldBeNil)
  153. So(sec.Key("TIME").InTime(zt, []time.Time{t, time.Now(), time.Now().Add(1 * time.Second)}).String(), ShouldEqual, t.String())
  154. Convey("Get value with candidates and default value", func() {
  155. So(sec.Key("STRING_404").In("str", []string{"str", "arr", "types"}), ShouldEqual, "str")
  156. So(sec.Key("FLOAT64_404").InFloat64(1.25, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25)
  157. So(sec.Key("INT_404").InInt(10, []int{10, 20, 30}), ShouldEqual, 10)
  158. So(sec.Key("INT64_404").InInt64(10, []int64{10, 20, 30}), ShouldEqual, 10)
  159. So(sec.Key("UINT_404").InUint(3, []uint{3, 6, 9}), ShouldEqual, 3)
  160. So(sec.Key("UINT_404").InUint64(3, []uint64{3, 6, 9}), ShouldEqual, 3)
  161. So(sec.Key("TIME_404").InTime(t, []time.Time{time.Now(), time.Now(), time.Now().Add(1 * time.Second)}).String(), ShouldEqual, t.String())
  162. })
  163. })
  164. Convey("Get values in range", func() {
  165. sec := cfg.Section("types")
  166. So(sec.Key("FLOAT64").RangeFloat64(0, 1, 2), ShouldEqual, 1.25)
  167. So(sec.Key("INT").RangeInt(0, 10, 20), ShouldEqual, 10)
  168. So(sec.Key("INT").RangeInt64(0, 10, 20), ShouldEqual, 10)
  169. minT, err := time.Parse(time.RFC3339, "0001-01-01T01:00:00Z")
  170. So(err, ShouldBeNil)
  171. midT, err := time.Parse(time.RFC3339, "2013-01-01T01:00:00Z")
  172. So(err, ShouldBeNil)
  173. maxT, err := time.Parse(time.RFC3339, "9999-01-01T01:00:00Z")
  174. So(err, ShouldBeNil)
  175. t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
  176. So(err, ShouldBeNil)
  177. So(sec.Key("TIME").RangeTime(t, minT, maxT).String(), ShouldEqual, t.String())
  178. Convey("Get value in range with default value", func() {
  179. So(sec.Key("FLOAT64").RangeFloat64(5, 0, 1), ShouldEqual, 5)
  180. So(sec.Key("INT").RangeInt(7, 0, 5), ShouldEqual, 7)
  181. So(sec.Key("INT").RangeInt64(7, 0, 5), ShouldEqual, 7)
  182. So(sec.Key("TIME").RangeTime(t, minT, midT).String(), ShouldEqual, t.String())
  183. })
  184. })
  185. Convey("Get values into slice", func() {
  186. sec := cfg.Section("array")
  187. So(strings.Join(sec.Key("STRINGS").Strings(","), ","), ShouldEqual, "en,zh,de")
  188. So(len(sec.Key("STRINGS_404").Strings(",")), ShouldEqual, 0)
  189. vals1 := sec.Key("FLOAT64S").Float64s(",")
  190. float64sEqual(vals1, 1.1, 2.2, 3.3)
  191. vals2 := sec.Key("INTS").Ints(",")
  192. intsEqual(vals2, 1, 2, 3)
  193. vals3 := sec.Key("INTS").Int64s(",")
  194. int64sEqual(vals3, 1, 2, 3)
  195. vals4 := sec.Key("UINTS").Uints(",")
  196. uintsEqual(vals4, 1, 2, 3)
  197. vals5 := sec.Key("UINTS").Uint64s(",")
  198. uint64sEqual(vals5, 1, 2, 3)
  199. t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
  200. So(err, ShouldBeNil)
  201. vals6 := sec.Key("TIMES").Times(",")
  202. timesEqual(vals6, t, t, t)
  203. })
  204. Convey("Get valid values into slice", func() {
  205. sec := cfg.Section("array")
  206. vals1 := sec.Key("FLOAT64S").ValidFloat64s(",")
  207. float64sEqual(vals1, 1.1, 2.2, 3.3)
  208. vals2 := sec.Key("INTS").ValidInts(",")
  209. intsEqual(vals2, 1, 2, 3)
  210. vals3 := sec.Key("INTS").ValidInt64s(",")
  211. int64sEqual(vals3, 1, 2, 3)
  212. vals4 := sec.Key("UINTS").ValidUints(",")
  213. uintsEqual(vals4, 1, 2, 3)
  214. vals5 := sec.Key("UINTS").ValidUint64s(",")
  215. uint64sEqual(vals5, 1, 2, 3)
  216. t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
  217. So(err, ShouldBeNil)
  218. vals6 := sec.Key("TIMES").ValidTimes(",")
  219. timesEqual(vals6, t, t, t)
  220. })
  221. Convey("Get values one type into slice of another type", func() {
  222. sec := cfg.Section("array")
  223. vals1 := sec.Key("STRINGS").ValidFloat64s(",")
  224. So(vals1, ShouldBeEmpty)
  225. vals2 := sec.Key("STRINGS").ValidInts(",")
  226. So(vals2, ShouldBeEmpty)
  227. vals3 := sec.Key("STRINGS").ValidInt64s(",")
  228. So(vals3, ShouldBeEmpty)
  229. vals4 := sec.Key("STRINGS").ValidUints(",")
  230. So(vals4, ShouldBeEmpty)
  231. vals5 := sec.Key("STRINGS").ValidUint64s(",")
  232. So(vals5, ShouldBeEmpty)
  233. vals6 := sec.Key("STRINGS").ValidTimes(",")
  234. So(vals6, ShouldBeEmpty)
  235. })
  236. Convey("Get valid values into slice without errors", func() {
  237. sec := cfg.Section("array")
  238. vals1, err := sec.Key("FLOAT64S").StrictFloat64s(",")
  239. So(err, ShouldBeNil)
  240. float64sEqual(vals1, 1.1, 2.2, 3.3)
  241. vals2, err := sec.Key("INTS").StrictInts(",")
  242. So(err, ShouldBeNil)
  243. intsEqual(vals2, 1, 2, 3)
  244. vals3, err := sec.Key("INTS").StrictInt64s(",")
  245. So(err, ShouldBeNil)
  246. int64sEqual(vals3, 1, 2, 3)
  247. vals4, err := sec.Key("UINTS").StrictUints(",")
  248. So(err, ShouldBeNil)
  249. uintsEqual(vals4, 1, 2, 3)
  250. vals5, err := sec.Key("UINTS").StrictUint64s(",")
  251. So(err, ShouldBeNil)
  252. uint64sEqual(vals5, 1, 2, 3)
  253. t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
  254. So(err, ShouldBeNil)
  255. vals6, err := sec.Key("TIMES").StrictTimes(",")
  256. So(err, ShouldBeNil)
  257. timesEqual(vals6, t, t, t)
  258. })
  259. Convey("Get invalid values into slice", func() {
  260. sec := cfg.Section("array")
  261. vals1, err := sec.Key("STRINGS").StrictFloat64s(",")
  262. So(vals1, ShouldBeEmpty)
  263. So(err, ShouldNotBeNil)
  264. vals2, err := sec.Key("STRINGS").StrictInts(",")
  265. So(vals2, ShouldBeEmpty)
  266. So(err, ShouldNotBeNil)
  267. vals3, err := sec.Key("STRINGS").StrictInt64s(",")
  268. So(vals3, ShouldBeEmpty)
  269. So(err, ShouldNotBeNil)
  270. vals4, err := sec.Key("STRINGS").StrictUints(",")
  271. So(vals4, ShouldBeEmpty)
  272. So(err, ShouldNotBeNil)
  273. vals5, err := sec.Key("STRINGS").StrictUint64s(",")
  274. So(vals5, ShouldBeEmpty)
  275. So(err, ShouldNotBeNil)
  276. vals6, err := sec.Key("STRINGS").StrictTimes(",")
  277. So(vals6, ShouldBeEmpty)
  278. So(err, ShouldNotBeNil)
  279. })
  280. Convey("Get key hash", func() {
  281. cfg.Section("").KeysHash()
  282. })
  283. Convey("Set key value", func() {
  284. k := cfg.Section("author").Key("NAME")
  285. k.SetValue("无闻")
  286. So(k.String(), ShouldEqual, "无闻")
  287. })
  288. Convey("Get key strings", func() {
  289. So(strings.Join(cfg.Section("types").KeyStrings(), ","), ShouldEqual, "STRING,BOOL,BOOL_FALSE,FLOAT64,INT,TIME,DURATION,UINT")
  290. })
  291. Convey("Delete a key", func() {
  292. cfg.Section("package.sub").DeleteKey("UNUSED_KEY")
  293. _, err := cfg.Section("package.sub").GetKey("UNUSED_KEY")
  294. So(err, ShouldNotBeNil)
  295. })
  296. Convey("Has Key (backwards compatible)", func() {
  297. sec := cfg.Section("package.sub")
  298. haskey1 := sec.Haskey("UNUSED_KEY")
  299. haskey2 := sec.Haskey("CLONE_URL")
  300. haskey3 := sec.Haskey("CLONE_URL_NO")
  301. So(haskey1, ShouldBeTrue)
  302. So(haskey2, ShouldBeTrue)
  303. So(haskey3, ShouldBeFalse)
  304. })
  305. Convey("Has Key", func() {
  306. sec := cfg.Section("package.sub")
  307. haskey1 := sec.HasKey("UNUSED_KEY")
  308. haskey2 := sec.HasKey("CLONE_URL")
  309. haskey3 := sec.HasKey("CLONE_URL_NO")
  310. So(haskey1, ShouldBeTrue)
  311. So(haskey2, ShouldBeTrue)
  312. So(haskey3, ShouldBeFalse)
  313. })
  314. Convey("Has Value", func() {
  315. sec := cfg.Section("author")
  316. hasvalue1 := sec.HasValue("Unknwon")
  317. hasvalue2 := sec.HasValue("doc")
  318. So(hasvalue1, ShouldBeTrue)
  319. So(hasvalue2, ShouldBeFalse)
  320. })
  321. })
  322. Convey("Test getting and setting bad values", t, func() {
  323. cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini")
  324. So(err, ShouldBeNil)
  325. So(cfg, ShouldNotBeNil)
  326. Convey("Create new key with empty name", func() {
  327. k, err := cfg.Section("").NewKey("", "")
  328. So(err, ShouldNotBeNil)
  329. So(k, ShouldBeNil)
  330. })
  331. Convey("Create new section with empty name", func() {
  332. s, err := cfg.NewSection("")
  333. So(err, ShouldNotBeNil)
  334. So(s, ShouldBeNil)
  335. })
  336. Convey("Create new sections with empty name", func() {
  337. So(cfg.NewSections(""), ShouldNotBeNil)
  338. })
  339. Convey("Get section that not exists", func() {
  340. s, err := cfg.GetSection("404")
  341. So(err, ShouldNotBeNil)
  342. So(s, ShouldBeNil)
  343. s = cfg.Section("404")
  344. So(s, ShouldNotBeNil)
  345. })
  346. })
  347. Convey("Test key hash clone", t, func() {
  348. cfg, err := Load([]byte(strings.Replace("network=tcp,addr=127.0.0.1:6379,db=4,pool_size=100,idle_timeout=180", ",", "\n", -1)))
  349. So(err, ShouldBeNil)
  350. for _, v := range cfg.Section("").KeysHash() {
  351. So(len(v), ShouldBeGreaterThan, 0)
  352. }
  353. })
  354. Convey("Key has empty value", t, func() {
  355. _conf := `key1=
  356. key2= ; comment`
  357. cfg, err := Load([]byte(_conf))
  358. So(err, ShouldBeNil)
  359. So(cfg.Section("").Key("key1").Value(), ShouldBeEmpty)
  360. })
  361. }
  362. func newTestFile(block bool) *File {
  363. c, _ := Load([]byte(_CONF_DATA))
  364. c.BlockMode = block
  365. return c
  366. }
  367. func Benchmark_Key_Value(b *testing.B) {
  368. c := newTestFile(true)
  369. for i := 0; i < b.N; i++ {
  370. c.Section("").Key("NAME").Value()
  371. }
  372. }
  373. func Benchmark_Key_Value_NonBlock(b *testing.B) {
  374. c := newTestFile(false)
  375. for i := 0; i < b.N; i++ {
  376. c.Section("").Key("NAME").Value()
  377. }
  378. }
  379. func Benchmark_Key_Value_ViaSection(b *testing.B) {
  380. c := newTestFile(true)
  381. sec := c.Section("")
  382. for i := 0; i < b.N; i++ {
  383. sec.Key("NAME").Value()
  384. }
  385. }
  386. func Benchmark_Key_Value_ViaSection_NonBlock(b *testing.B) {
  387. c := newTestFile(false)
  388. sec := c.Section("")
  389. for i := 0; i < b.N; i++ {
  390. sec.Key("NAME").Value()
  391. }
  392. }
  393. func Benchmark_Key_Value_Direct(b *testing.B) {
  394. c := newTestFile(true)
  395. key := c.Section("").Key("NAME")
  396. for i := 0; i < b.N; i++ {
  397. key.Value()
  398. }
  399. }
  400. func Benchmark_Key_Value_Direct_NonBlock(b *testing.B) {
  401. c := newTestFile(false)
  402. key := c.Section("").Key("NAME")
  403. for i := 0; i < b.N; i++ {
  404. key.Value()
  405. }
  406. }
  407. func Benchmark_Key_String(b *testing.B) {
  408. c := newTestFile(true)
  409. for i := 0; i < b.N; i++ {
  410. _ = c.Section("").Key("NAME").String()
  411. }
  412. }
  413. func Benchmark_Key_String_NonBlock(b *testing.B) {
  414. c := newTestFile(false)
  415. for i := 0; i < b.N; i++ {
  416. _ = c.Section("").Key("NAME").String()
  417. }
  418. }
  419. func Benchmark_Key_String_ViaSection(b *testing.B) {
  420. c := newTestFile(true)
  421. sec := c.Section("")
  422. for i := 0; i < b.N; i++ {
  423. _ = sec.Key("NAME").String()
  424. }
  425. }
  426. func Benchmark_Key_String_ViaSection_NonBlock(b *testing.B) {
  427. c := newTestFile(false)
  428. sec := c.Section("")
  429. for i := 0; i < b.N; i++ {
  430. _ = sec.Key("NAME").String()
  431. }
  432. }
  433. func Benchmark_Key_SetValue(b *testing.B) {
  434. c := newTestFile(true)
  435. for i := 0; i < b.N; i++ {
  436. c.Section("").Key("NAME").SetValue("10")
  437. }
  438. }
  439. func Benchmark_Key_SetValue_VisSection(b *testing.B) {
  440. c := newTestFile(true)
  441. sec := c.Section("")
  442. for i := 0; i < b.N; i++ {
  443. sec.Key("NAME").SetValue("10")
  444. }
  445. }