config_test.go 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310
  1. package conf
  2. import (
  3. "os"
  4. "reflect"
  5. "testing"
  6. "github.com/stretchr/testify/assert"
  7. "github.com/zeromicro/go-zero/core/fs"
  8. "github.com/zeromicro/go-zero/core/hash"
  9. )
  10. var dupErr conflictKeyError
  11. func TestLoadConfig_notExists(t *testing.T) {
  12. assert.NotNil(t, Load("not_a_file", nil))
  13. }
  14. func TestLoadConfig_notRecogFile(t *testing.T) {
  15. filename, err := fs.TempFilenameWithText("hello")
  16. assert.Nil(t, err)
  17. defer os.Remove(filename)
  18. assert.NotNil(t, LoadConfig(filename, nil))
  19. }
  20. func TestConfigJson(t *testing.T) {
  21. tests := []string{
  22. ".json",
  23. ".yaml",
  24. ".yml",
  25. }
  26. text := `{
  27. "a": "foo",
  28. "b": 1,
  29. "c": "${FOO}",
  30. "d": "abcd!@#$112"
  31. }`
  32. for _, test := range tests {
  33. test := test
  34. t.Run(test, func(t *testing.T) {
  35. os.Setenv("FOO", "2")
  36. defer os.Unsetenv("FOO")
  37. tmpfile, err := createTempFile(test, text)
  38. assert.Nil(t, err)
  39. defer os.Remove(tmpfile)
  40. var val struct {
  41. A string `json:"a"`
  42. B int `json:"b"`
  43. C string `json:"c"`
  44. D string `json:"d"`
  45. }
  46. MustLoad(tmpfile, &val)
  47. assert.Equal(t, "foo", val.A)
  48. assert.Equal(t, 1, val.B)
  49. assert.Equal(t, "${FOO}", val.C)
  50. assert.Equal(t, "abcd!@#$112", val.D)
  51. })
  52. }
  53. }
  54. func TestLoadFromJsonBytesArray(t *testing.T) {
  55. input := []byte(`{"users": [{"name": "foo"}, {"Name": "bar"}]}`)
  56. var val struct {
  57. Users []struct {
  58. Name string
  59. }
  60. }
  61. assert.NoError(t, LoadConfigFromJsonBytes(input, &val))
  62. var expect []string
  63. for _, user := range val.Users {
  64. expect = append(expect, user.Name)
  65. }
  66. assert.EqualValues(t, []string{"foo", "bar"}, expect)
  67. }
  68. func TestConfigToml(t *testing.T) {
  69. text := `a = "foo"
  70. b = 1
  71. c = "${FOO}"
  72. d = "abcd!@#$112"
  73. `
  74. os.Setenv("FOO", "2")
  75. defer os.Unsetenv("FOO")
  76. tmpfile, err := createTempFile(".toml", text)
  77. assert.Nil(t, err)
  78. defer os.Remove(tmpfile)
  79. var val struct {
  80. A string `json:"a"`
  81. B int `json:"b"`
  82. C string `json:"c"`
  83. D string `json:"d"`
  84. }
  85. MustLoad(tmpfile, &val)
  86. assert.Equal(t, "foo", val.A)
  87. assert.Equal(t, 1, val.B)
  88. assert.Equal(t, "${FOO}", val.C)
  89. assert.Equal(t, "abcd!@#$112", val.D)
  90. }
  91. func TestConfigOptional(t *testing.T) {
  92. text := `a = "foo"
  93. b = 1
  94. c = "FOO"
  95. d = "abcd"
  96. `
  97. tmpfile, err := createTempFile(".toml", text)
  98. assert.Nil(t, err)
  99. defer os.Remove(tmpfile)
  100. var val struct {
  101. A string `json:"a"`
  102. B int `json:"b,optional"`
  103. C string `json:"c,optional=B"`
  104. D string `json:"d,optional=b"`
  105. }
  106. if assert.NoError(t, Load(tmpfile, &val)) {
  107. assert.Equal(t, "foo", val.A)
  108. assert.Equal(t, 1, val.B)
  109. assert.Equal(t, "FOO", val.C)
  110. assert.Equal(t, "abcd", val.D)
  111. }
  112. }
  113. func TestConfigWithLower(t *testing.T) {
  114. text := `a = "foo"
  115. b = 1
  116. `
  117. tmpfile, err := createTempFile(".toml", text)
  118. assert.Nil(t, err)
  119. defer os.Remove(tmpfile)
  120. var val struct {
  121. A string `json:"a"`
  122. b int
  123. }
  124. if assert.NoError(t, Load(tmpfile, &val)) {
  125. assert.Equal(t, "foo", val.A)
  126. assert.Equal(t, 0, val.b)
  127. }
  128. }
  129. func TestConfigJsonCanonical(t *testing.T) {
  130. text := []byte(`{"a": "foo", "B": "bar"}`)
  131. var val1 struct {
  132. A string `json:"a"`
  133. B string `json:"b"`
  134. }
  135. var val2 struct {
  136. A string
  137. B string
  138. }
  139. assert.NoError(t, LoadFromJsonBytes(text, &val1))
  140. assert.Equal(t, "foo", val1.A)
  141. assert.Equal(t, "bar", val1.B)
  142. assert.NoError(t, LoadFromJsonBytes(text, &val2))
  143. assert.Equal(t, "foo", val2.A)
  144. assert.Equal(t, "bar", val2.B)
  145. }
  146. func TestConfigTomlCanonical(t *testing.T) {
  147. text := []byte(`a = "foo"
  148. B = "bar"`)
  149. var val1 struct {
  150. A string `json:"a"`
  151. B string `json:"b"`
  152. }
  153. var val2 struct {
  154. A string
  155. B string
  156. }
  157. assert.NoError(t, LoadFromTomlBytes(text, &val1))
  158. assert.Equal(t, "foo", val1.A)
  159. assert.Equal(t, "bar", val1.B)
  160. assert.NoError(t, LoadFromTomlBytes(text, &val2))
  161. assert.Equal(t, "foo", val2.A)
  162. assert.Equal(t, "bar", val2.B)
  163. }
  164. func TestConfigYamlCanonical(t *testing.T) {
  165. text := []byte(`a: foo
  166. B: bar`)
  167. var val1 struct {
  168. A string `json:"a"`
  169. B string `json:"b"`
  170. }
  171. var val2 struct {
  172. A string
  173. B string
  174. }
  175. assert.NoError(t, LoadConfigFromYamlBytes(text, &val1))
  176. assert.Equal(t, "foo", val1.A)
  177. assert.Equal(t, "bar", val1.B)
  178. assert.NoError(t, LoadFromYamlBytes(text, &val2))
  179. assert.Equal(t, "foo", val2.A)
  180. assert.Equal(t, "bar", val2.B)
  181. }
  182. func TestConfigTomlEnv(t *testing.T) {
  183. text := `a = "foo"
  184. b = 1
  185. c = "${FOO}"
  186. d = "abcd!@#112"
  187. `
  188. os.Setenv("FOO", "2")
  189. defer os.Unsetenv("FOO")
  190. tmpfile, err := createTempFile(".toml", text)
  191. assert.Nil(t, err)
  192. defer os.Remove(tmpfile)
  193. var val struct {
  194. A string `json:"a"`
  195. B int `json:"b"`
  196. C string `json:"c"`
  197. D string `json:"d"`
  198. }
  199. MustLoad(tmpfile, &val, UseEnv())
  200. assert.Equal(t, "foo", val.A)
  201. assert.Equal(t, 1, val.B)
  202. assert.Equal(t, "2", val.C)
  203. assert.Equal(t, "abcd!@#112", val.D)
  204. }
  205. func TestConfigJsonEnv(t *testing.T) {
  206. tests := []string{
  207. ".json",
  208. ".yaml",
  209. ".yml",
  210. }
  211. text := `{
  212. "a": "foo",
  213. "b": 1,
  214. "c": "${FOO}",
  215. "d": "abcd!@#$a12 3"
  216. }`
  217. for _, test := range tests {
  218. test := test
  219. t.Run(test, func(t *testing.T) {
  220. os.Setenv("FOO", "2")
  221. defer os.Unsetenv("FOO")
  222. tmpfile, err := createTempFile(test, text)
  223. assert.Nil(t, err)
  224. defer os.Remove(tmpfile)
  225. var val struct {
  226. A string `json:"a"`
  227. B int `json:"b"`
  228. C string `json:"c"`
  229. D string `json:"d"`
  230. }
  231. MustLoad(tmpfile, &val, UseEnv())
  232. assert.Equal(t, "foo", val.A)
  233. assert.Equal(t, 1, val.B)
  234. assert.Equal(t, "2", val.C)
  235. assert.Equal(t, "abcd!@# 3", val.D)
  236. })
  237. }
  238. }
  239. func TestToCamelCase(t *testing.T) {
  240. tests := []struct {
  241. input string
  242. expect string
  243. }{
  244. {
  245. input: "",
  246. expect: "",
  247. },
  248. {
  249. input: "A",
  250. expect: "a",
  251. },
  252. {
  253. input: "a",
  254. expect: "a",
  255. },
  256. {
  257. input: "hello_world",
  258. expect: "hello_world",
  259. },
  260. {
  261. input: "Hello_world",
  262. expect: "hello_world",
  263. },
  264. {
  265. input: "hello_World",
  266. expect: "hello_world",
  267. },
  268. {
  269. input: "helloWorld",
  270. expect: "helloworld",
  271. },
  272. {
  273. input: "HelloWorld",
  274. expect: "helloworld",
  275. },
  276. {
  277. input: "hello World",
  278. expect: "hello world",
  279. },
  280. {
  281. input: "Hello World",
  282. expect: "hello world",
  283. },
  284. {
  285. input: "Hello World",
  286. expect: "hello world",
  287. },
  288. {
  289. input: "Hello World foo_bar",
  290. expect: "hello world foo_bar",
  291. },
  292. {
  293. input: "Hello World foo_Bar",
  294. expect: "hello world foo_bar",
  295. },
  296. {
  297. input: "Hello World Foo_bar",
  298. expect: "hello world foo_bar",
  299. },
  300. {
  301. input: "Hello World Foo_Bar",
  302. expect: "hello world foo_bar",
  303. },
  304. {
  305. input: "Hello.World Foo_Bar",
  306. expect: "hello.world foo_bar",
  307. },
  308. {
  309. input: "你好 World Foo_Bar",
  310. expect: "你好 world foo_bar",
  311. },
  312. }
  313. for _, test := range tests {
  314. test := test
  315. t.Run(test.input, func(t *testing.T) {
  316. assert.Equal(t, test.expect, toLowerCase(test.input))
  317. })
  318. }
  319. }
  320. func TestLoadFromJsonBytesError(t *testing.T) {
  321. var val struct{}
  322. assert.Error(t, LoadFromJsonBytes([]byte(`hello`), &val))
  323. }
  324. func TestLoadFromTomlBytesError(t *testing.T) {
  325. var val struct{}
  326. assert.Error(t, LoadFromTomlBytes([]byte(`hello`), &val))
  327. }
  328. func TestLoadFromYamlBytesError(t *testing.T) {
  329. var val struct{}
  330. assert.Error(t, LoadFromYamlBytes([]byte(`':hello`), &val))
  331. }
  332. func TestLoadFromYamlBytes(t *testing.T) {
  333. input := []byte(`layer1:
  334. layer2:
  335. layer3: foo`)
  336. var val struct {
  337. Layer1 struct {
  338. Layer2 struct {
  339. Layer3 string
  340. }
  341. }
  342. }
  343. assert.NoError(t, LoadFromYamlBytes(input, &val))
  344. assert.Equal(t, "foo", val.Layer1.Layer2.Layer3)
  345. }
  346. func TestLoadFromYamlBytesTerm(t *testing.T) {
  347. input := []byte(`layer1:
  348. layer2:
  349. tls_conf: foo`)
  350. var val struct {
  351. Layer1 struct {
  352. Layer2 struct {
  353. Layer3 string `json:"tls_conf"`
  354. }
  355. }
  356. }
  357. assert.NoError(t, LoadFromYamlBytes(input, &val))
  358. assert.Equal(t, "foo", val.Layer1.Layer2.Layer3)
  359. }
  360. func TestLoadFromYamlBytesLayers(t *testing.T) {
  361. input := []byte(`layer1:
  362. layer2:
  363. layer3: foo`)
  364. var val struct {
  365. Value string `json:"Layer1.Layer2.Layer3"`
  366. }
  367. assert.NoError(t, LoadFromYamlBytes(input, &val))
  368. assert.Equal(t, "foo", val.Value)
  369. }
  370. func TestLoadFromYamlItemOverlay(t *testing.T) {
  371. type (
  372. Redis struct {
  373. Host string
  374. Port int
  375. }
  376. RedisKey struct {
  377. Redis
  378. Key string
  379. }
  380. Server struct {
  381. Redis RedisKey
  382. }
  383. TestConfig struct {
  384. Server
  385. Redis Redis
  386. }
  387. )
  388. input := []byte(`Redis:
  389. Host: localhost
  390. Port: 6379
  391. Key: test
  392. `)
  393. var c TestConfig
  394. assert.ErrorAs(t, LoadFromYamlBytes(input, &c), &dupErr)
  395. }
  396. func TestLoadFromYamlItemOverlayReverse(t *testing.T) {
  397. type (
  398. Redis struct {
  399. Host string
  400. Port int
  401. }
  402. RedisKey struct {
  403. Redis
  404. Key string
  405. }
  406. Server struct {
  407. Redis Redis
  408. }
  409. TestConfig struct {
  410. Redis RedisKey
  411. Server
  412. }
  413. )
  414. input := []byte(`Redis:
  415. Host: localhost
  416. Port: 6379
  417. Key: test
  418. `)
  419. var c TestConfig
  420. assert.ErrorAs(t, LoadFromYamlBytes(input, &c), &dupErr)
  421. }
  422. func TestLoadFromYamlItemOverlayWithMap(t *testing.T) {
  423. type (
  424. Redis struct {
  425. Host string
  426. Port int
  427. }
  428. RedisKey struct {
  429. Redis
  430. Key string
  431. }
  432. Server struct {
  433. Redis RedisKey
  434. }
  435. TestConfig struct {
  436. Server
  437. Redis map[string]interface{}
  438. }
  439. )
  440. input := []byte(`Redis:
  441. Host: localhost
  442. Port: 6379
  443. Key: test
  444. `)
  445. var c TestConfig
  446. assert.ErrorAs(t, LoadFromYamlBytes(input, &c), &dupErr)
  447. }
  448. func TestUnmarshalJsonBytesMap(t *testing.T) {
  449. input := []byte(`{"foo":{"/mtproto.RPCTos": "bff.bff","bar":"baz"}}`)
  450. var val struct {
  451. Foo map[string]string
  452. }
  453. assert.NoError(t, LoadFromJsonBytes(input, &val))
  454. assert.Equal(t, "bff.bff", val.Foo["/mtproto.RPCTos"])
  455. assert.Equal(t, "baz", val.Foo["bar"])
  456. }
  457. func TestUnmarshalJsonBytesMapWithSliceElements(t *testing.T) {
  458. input := []byte(`{"foo":{"/mtproto.RPCTos": ["bff.bff", "any"],"bar":["baz", "qux"]}}`)
  459. var val struct {
  460. Foo map[string][]string
  461. }
  462. assert.NoError(t, LoadFromJsonBytes(input, &val))
  463. assert.EqualValues(t, []string{"bff.bff", "any"}, val.Foo["/mtproto.RPCTos"])
  464. assert.EqualValues(t, []string{"baz", "qux"}, val.Foo["bar"])
  465. }
  466. func TestUnmarshalJsonBytesMapWithSliceOfStructs(t *testing.T) {
  467. input := []byte(`{"foo":{
  468. "/mtproto.RPCTos": [{"bar": "any"}],
  469. "bar":[{"bar": "qux"}, {"bar": "ever"}]}}`)
  470. var val struct {
  471. Foo map[string][]struct {
  472. Bar string
  473. }
  474. }
  475. assert.NoError(t, LoadFromJsonBytes(input, &val))
  476. assert.Equal(t, 1, len(val.Foo["/mtproto.RPCTos"]))
  477. assert.Equal(t, "any", val.Foo["/mtproto.RPCTos"][0].Bar)
  478. assert.Equal(t, 2, len(val.Foo["bar"]))
  479. assert.Equal(t, "qux", val.Foo["bar"][0].Bar)
  480. assert.Equal(t, "ever", val.Foo["bar"][1].Bar)
  481. }
  482. func TestUnmarshalJsonBytesWithAnonymousField(t *testing.T) {
  483. type (
  484. Int int
  485. InnerConf struct {
  486. Name string
  487. }
  488. Conf struct {
  489. Int
  490. InnerConf
  491. }
  492. )
  493. var (
  494. input = []byte(`{"Name": "hello", "int": 3}`)
  495. c Conf
  496. )
  497. assert.NoError(t, LoadFromJsonBytes(input, &c))
  498. assert.Equal(t, "hello", c.Name)
  499. assert.Equal(t, Int(3), c.Int)
  500. }
  501. func TestUnmarshalJsonBytesWithMapValueOfStruct(t *testing.T) {
  502. type (
  503. Value struct {
  504. Name string
  505. }
  506. Config struct {
  507. Items map[string]Value
  508. }
  509. )
  510. var inputs = [][]byte{
  511. []byte(`{"Items": {"Key":{"Name": "foo"}}}`),
  512. []byte(`{"Items": {"Key":{"Name": "foo"}}}`),
  513. []byte(`{"items": {"key":{"name": "foo"}}}`),
  514. []byte(`{"items": {"key":{"name": "foo"}}}`),
  515. }
  516. for _, input := range inputs {
  517. var c Config
  518. if assert.NoError(t, LoadFromJsonBytes(input, &c)) {
  519. assert.Equal(t, 1, len(c.Items))
  520. for _, v := range c.Items {
  521. assert.Equal(t, "foo", v.Name)
  522. }
  523. }
  524. }
  525. }
  526. func TestUnmarshalJsonBytesWithMapTypeValueOfStruct(t *testing.T) {
  527. type (
  528. Value struct {
  529. Name string
  530. }
  531. Map map[string]Value
  532. Config struct {
  533. Map
  534. }
  535. )
  536. var inputs = [][]byte{
  537. []byte(`{"Map": {"Key":{"Name": "foo"}}}`),
  538. []byte(`{"Map": {"Key":{"Name": "foo"}}}`),
  539. []byte(`{"map": {"key":{"name": "foo"}}}`),
  540. []byte(`{"map": {"key":{"name": "foo"}}}`),
  541. }
  542. for _, input := range inputs {
  543. var c Config
  544. if assert.NoError(t, LoadFromJsonBytes(input, &c)) {
  545. assert.Equal(t, 1, len(c.Map))
  546. for _, v := range c.Map {
  547. assert.Equal(t, "foo", v.Name)
  548. }
  549. }
  550. }
  551. }
  552. func Test_FieldOverwrite(t *testing.T) {
  553. t.Run("normal", func(t *testing.T) {
  554. type Base struct {
  555. Name string
  556. }
  557. type St1 struct {
  558. Base
  559. Name2 string
  560. }
  561. type St2 struct {
  562. Base
  563. Name2 string
  564. }
  565. type St3 struct {
  566. *Base
  567. Name2 string
  568. }
  569. type St4 struct {
  570. *Base
  571. Name2 *string
  572. }
  573. validate := func(val any) {
  574. input := []byte(`{"Name": "hello", "Name2": "world"}`)
  575. assert.NoError(t, LoadFromJsonBytes(input, val))
  576. }
  577. validate(&St1{})
  578. validate(&St2{})
  579. validate(&St3{})
  580. validate(&St4{})
  581. })
  582. t.Run("Inherit Override", func(t *testing.T) {
  583. type Base struct {
  584. Name string
  585. }
  586. type St1 struct {
  587. Base
  588. Name string
  589. }
  590. type St2 struct {
  591. Base
  592. Name int
  593. }
  594. type St3 struct {
  595. *Base
  596. Name int
  597. }
  598. type St4 struct {
  599. *Base
  600. Name *string
  601. }
  602. validate := func(val any) {
  603. input := []byte(`{"Name": "hello"}`)
  604. err := LoadFromJsonBytes(input, val)
  605. assert.ErrorAs(t, err, &dupErr)
  606. assert.Equal(t, newConflictKeyError("name").Error(), err.Error())
  607. }
  608. validate(&St1{})
  609. validate(&St2{})
  610. validate(&St3{})
  611. validate(&St4{})
  612. })
  613. t.Run("Inherit more", func(t *testing.T) {
  614. type Base1 struct {
  615. Name string
  616. }
  617. type St0 struct {
  618. Base1
  619. Name string
  620. }
  621. type St1 struct {
  622. St0
  623. Name string
  624. }
  625. type St2 struct {
  626. St0
  627. Name int
  628. }
  629. type St3 struct {
  630. *St0
  631. Name int
  632. }
  633. type St4 struct {
  634. *St0
  635. Name *int
  636. }
  637. validate := func(val any) {
  638. input := []byte(`{"Name": "hello"}`)
  639. err := LoadFromJsonBytes(input, val)
  640. assert.ErrorAs(t, err, &dupErr)
  641. assert.Error(t, err)
  642. }
  643. validate(&St0{})
  644. validate(&St1{})
  645. validate(&St2{})
  646. validate(&St3{})
  647. validate(&St4{})
  648. })
  649. }
  650. func TestFieldOverwriteComplicated(t *testing.T) {
  651. t.Run("double maps", func(t *testing.T) {
  652. type (
  653. Base1 struct {
  654. Values map[string]string
  655. }
  656. Base2 struct {
  657. Values map[string]string
  658. }
  659. Config struct {
  660. Base1
  661. Base2
  662. }
  663. )
  664. var c Config
  665. input := []byte(`{"Values": {"Key": "Value"}}`)
  666. assert.ErrorAs(t, LoadFromJsonBytes(input, &c), &dupErr)
  667. })
  668. t.Run("merge children", func(t *testing.T) {
  669. type (
  670. Inner1 struct {
  671. Name string
  672. }
  673. Inner2 struct {
  674. Age int
  675. }
  676. Base1 struct {
  677. Inner Inner1
  678. }
  679. Base2 struct {
  680. Inner Inner2
  681. }
  682. Config struct {
  683. Base1
  684. Base2
  685. }
  686. )
  687. var c Config
  688. input := []byte(`{"Inner": {"Name": "foo", "Age": 10}}`)
  689. if assert.NoError(t, LoadFromJsonBytes(input, &c)) {
  690. assert.Equal(t, "foo", c.Base1.Inner.Name)
  691. assert.Equal(t, 10, c.Base2.Inner.Age)
  692. }
  693. })
  694. t.Run("overwritten maps", func(t *testing.T) {
  695. type (
  696. Inner struct {
  697. Map map[string]string
  698. }
  699. Config struct {
  700. Map map[string]string
  701. Inner
  702. }
  703. )
  704. var c Config
  705. input := []byte(`{"Inner": {"Map": {"Key": "Value"}}}`)
  706. assert.ErrorAs(t, LoadFromJsonBytes(input, &c), &dupErr)
  707. })
  708. t.Run("overwritten nested maps", func(t *testing.T) {
  709. type (
  710. Inner struct {
  711. Map map[string]string
  712. }
  713. Middle1 struct {
  714. Map map[string]string
  715. Inner
  716. }
  717. Middle2 struct {
  718. Map map[string]string
  719. Inner
  720. }
  721. Config struct {
  722. Middle1
  723. Middle2
  724. }
  725. )
  726. var c Config
  727. input := []byte(`{"Middle1": {"Inner": {"Map": {"Key": "Value"}}}}`)
  728. assert.ErrorAs(t, LoadFromJsonBytes(input, &c), &dupErr)
  729. })
  730. t.Run("overwritten outer/inner maps", func(t *testing.T) {
  731. type (
  732. Inner struct {
  733. Map map[string]string
  734. }
  735. Middle struct {
  736. Inner
  737. Map map[string]string
  738. }
  739. Config struct {
  740. Middle
  741. }
  742. )
  743. var c Config
  744. input := []byte(`{"Middle": {"Inner": {"Map": {"Key": "Value"}}}}`)
  745. assert.ErrorAs(t, LoadFromJsonBytes(input, &c), &dupErr)
  746. })
  747. t.Run("overwritten anonymous maps", func(t *testing.T) {
  748. type (
  749. Inner struct {
  750. Map map[string]string
  751. }
  752. Middle struct {
  753. Inner
  754. Map map[string]string
  755. }
  756. Elem map[string]Middle
  757. Config struct {
  758. Elem
  759. }
  760. )
  761. var c Config
  762. input := []byte(`{"Elem": {"Key": {"Inner": {"Map": {"Key": "Value"}}}}}`)
  763. assert.ErrorAs(t, LoadFromJsonBytes(input, &c), &dupErr)
  764. })
  765. t.Run("overwritten primitive and map", func(t *testing.T) {
  766. type (
  767. Inner struct {
  768. Value string
  769. }
  770. Elem map[string]Inner
  771. Named struct {
  772. Elem string
  773. }
  774. Config struct {
  775. Named
  776. Elem
  777. }
  778. )
  779. var c Config
  780. input := []byte(`{"Elem": {"Key": {"Value": "Value"}}}`)
  781. assert.ErrorAs(t, LoadFromJsonBytes(input, &c), &dupErr)
  782. })
  783. t.Run("overwritten map and slice", func(t *testing.T) {
  784. type (
  785. Inner struct {
  786. Value string
  787. }
  788. Elem []Inner
  789. Named struct {
  790. Elem string
  791. }
  792. Config struct {
  793. Named
  794. Elem
  795. }
  796. )
  797. var c Config
  798. input := []byte(`{"Elem": {"Key": {"Value": "Value"}}}`)
  799. assert.ErrorAs(t, LoadFromJsonBytes(input, &c), &dupErr)
  800. })
  801. t.Run("overwritten map and string", func(t *testing.T) {
  802. type (
  803. Elem string
  804. Named struct {
  805. Elem string
  806. }
  807. Config struct {
  808. Named
  809. Elem
  810. }
  811. )
  812. var c Config
  813. input := []byte(`{"Elem": {"Key": {"Value": "Value"}}}`)
  814. assert.ErrorAs(t, LoadFromJsonBytes(input, &c), &dupErr)
  815. })
  816. }
  817. func TestLoadNamedFieldOverwritten(t *testing.T) {
  818. t.Run("overwritten named struct", func(t *testing.T) {
  819. type (
  820. Elem string
  821. Named struct {
  822. Elem string
  823. }
  824. Base struct {
  825. Named
  826. Elem
  827. }
  828. Config struct {
  829. Val Base
  830. }
  831. )
  832. var c Config
  833. input := []byte(`{"Val": {"Elem": {"Key": {"Value": "Value"}}}}`)
  834. assert.ErrorAs(t, LoadFromJsonBytes(input, &c), &dupErr)
  835. })
  836. t.Run("overwritten named []struct", func(t *testing.T) {
  837. type (
  838. Elem string
  839. Named struct {
  840. Elem string
  841. }
  842. Base struct {
  843. Named
  844. Elem
  845. }
  846. Config struct {
  847. Vals []Base
  848. }
  849. )
  850. var c Config
  851. input := []byte(`{"Vals": [{"Elem": {"Key": {"Value": "Value"}}}]}`)
  852. assert.ErrorAs(t, LoadFromJsonBytes(input, &c), &dupErr)
  853. })
  854. t.Run("overwritten named map[string]struct", func(t *testing.T) {
  855. type (
  856. Elem string
  857. Named struct {
  858. Elem string
  859. }
  860. Base struct {
  861. Named
  862. Elem
  863. }
  864. Config struct {
  865. Vals map[string]Base
  866. }
  867. )
  868. var c Config
  869. input := []byte(`{"Vals": {"Key": {"Elem": {"Key": {"Value": "Value"}}}}}`)
  870. assert.ErrorAs(t, LoadFromJsonBytes(input, &c), &dupErr)
  871. })
  872. t.Run("overwritten named *struct", func(t *testing.T) {
  873. type (
  874. Elem string
  875. Named struct {
  876. Elem string
  877. }
  878. Base struct {
  879. Named
  880. Elem
  881. }
  882. Config struct {
  883. Vals *Base
  884. }
  885. )
  886. var c Config
  887. input := []byte(`{"Vals": [{"Elem": {"Key": {"Value": "Value"}}}]}`)
  888. assert.ErrorAs(t, LoadFromJsonBytes(input, &c), &dupErr)
  889. })
  890. t.Run("overwritten named struct", func(t *testing.T) {
  891. type (
  892. Named struct {
  893. Elem string
  894. }
  895. Base struct {
  896. Named
  897. Elem Named
  898. }
  899. Config struct {
  900. Val Base
  901. }
  902. )
  903. var c Config
  904. input := []byte(`{"Val": {"Elem": "Value"}}`)
  905. assert.ErrorAs(t, LoadFromJsonBytes(input, &c), &dupErr)
  906. })
  907. t.Run("overwritten named struct", func(t *testing.T) {
  908. type Config struct {
  909. Val chan int
  910. }
  911. var c Config
  912. input := []byte(`{"Val": 1}`)
  913. assert.Error(t, LoadFromJsonBytes(input, &c))
  914. })
  915. }
  916. func TestLoadLowerMemberShouldNotConflict(t *testing.T) {
  917. type (
  918. Redis struct {
  919. db uint
  920. }
  921. Config struct {
  922. db uint
  923. Redis
  924. }
  925. )
  926. var c Config
  927. assert.NoError(t, LoadFromJsonBytes([]byte(`{}`), &c))
  928. assert.Zero(t, c.db)
  929. assert.Zero(t, c.Redis.db)
  930. }
  931. func TestFillDefaultUnmarshal(t *testing.T) {
  932. t.Run("nil", func(t *testing.T) {
  933. type St struct{}
  934. err := FillDefault(St{})
  935. assert.Error(t, err)
  936. })
  937. t.Run("not nil", func(t *testing.T) {
  938. type St struct{}
  939. err := FillDefault(&St{})
  940. assert.NoError(t, err)
  941. })
  942. t.Run("default", func(t *testing.T) {
  943. type St struct {
  944. A string `json:",default=a"`
  945. B string
  946. }
  947. var st St
  948. err := FillDefault(&st)
  949. assert.NoError(t, err)
  950. assert.Equal(t, st.A, "a")
  951. })
  952. t.Run("env", func(t *testing.T) {
  953. type St struct {
  954. A string `json:",default=a"`
  955. B string
  956. C string `json:",env=TEST_C"`
  957. }
  958. t.Setenv("TEST_C", "c")
  959. var st St
  960. err := FillDefault(&st)
  961. assert.NoError(t, err)
  962. assert.Equal(t, st.A, "a")
  963. assert.Equal(t, st.C, "c")
  964. })
  965. t.Run("has value", func(t *testing.T) {
  966. type St struct {
  967. A string `json:",default=a"`
  968. B string
  969. }
  970. var st = St{
  971. A: "b",
  972. }
  973. err := FillDefault(&st)
  974. assert.Error(t, err)
  975. })
  976. }
  977. func TestConfigWithJsonTag(t *testing.T) {
  978. t.Run("map with value", func(t *testing.T) {
  979. var input = []byte(`[Value]
  980. [Value.first]
  981. Email = "foo"
  982. [Value.second]
  983. Email = "bar"`)
  984. type Value struct {
  985. Email string
  986. }
  987. type Config struct {
  988. ValueMap map[string]Value `json:"Value"`
  989. }
  990. var c Config
  991. if assert.NoError(t, LoadFromTomlBytes(input, &c)) {
  992. assert.Len(t, c.ValueMap, 2)
  993. }
  994. })
  995. t.Run("map with ptr value", func(t *testing.T) {
  996. var input = []byte(`[Value]
  997. [Value.first]
  998. Email = "foo"
  999. [Value.second]
  1000. Email = "bar"`)
  1001. type Value struct {
  1002. Email string
  1003. }
  1004. type Config struct {
  1005. ValueMap map[string]*Value `json:"Value"`
  1006. }
  1007. var c Config
  1008. if assert.NoError(t, LoadFromTomlBytes(input, &c)) {
  1009. assert.Len(t, c.ValueMap, 2)
  1010. }
  1011. })
  1012. t.Run("map with optional", func(t *testing.T) {
  1013. var input = []byte(`[Value]
  1014. [Value.first]
  1015. Email = "foo"
  1016. [Value.second]
  1017. Email = "bar"`)
  1018. type Value struct {
  1019. Email string
  1020. }
  1021. type Config struct {
  1022. Value map[string]Value `json:",optional"`
  1023. }
  1024. var c Config
  1025. if assert.NoError(t, LoadFromTomlBytes(input, &c)) {
  1026. assert.Len(t, c.Value, 2)
  1027. }
  1028. })
  1029. t.Run("map with empty tag", func(t *testing.T) {
  1030. var input = []byte(`[Value]
  1031. [Value.first]
  1032. Email = "foo"
  1033. [Value.second]
  1034. Email = "bar"`)
  1035. type Value struct {
  1036. Email string
  1037. }
  1038. type Config struct {
  1039. Value map[string]Value `json:" "`
  1040. }
  1041. var c Config
  1042. if assert.NoError(t, LoadFromTomlBytes(input, &c)) {
  1043. assert.Len(t, c.Value, 2)
  1044. }
  1045. })
  1046. }
  1047. func Test_getFullName(t *testing.T) {
  1048. assert.Equal(t, "a.b", getFullName("a", "b"))
  1049. assert.Equal(t, "a", getFullName("", "a"))
  1050. }
  1051. func Test_buildFieldsInfo(t *testing.T) {
  1052. type ParentSt struct {
  1053. Name string
  1054. M map[string]int
  1055. }
  1056. tests := []struct {
  1057. name string
  1058. t reflect.Type
  1059. ok bool
  1060. containsKey string
  1061. }{
  1062. {
  1063. name: "normal",
  1064. t: reflect.TypeOf(struct{ A string }{}),
  1065. ok: true,
  1066. },
  1067. {
  1068. name: "struct anonymous",
  1069. t: reflect.TypeOf(struct {
  1070. ParentSt
  1071. Name string
  1072. }{}),
  1073. ok: false,
  1074. containsKey: newConflictKeyError("name").Error(),
  1075. },
  1076. {
  1077. name: "struct ptr anonymous",
  1078. t: reflect.TypeOf(struct {
  1079. *ParentSt
  1080. Name string
  1081. }{}),
  1082. ok: false,
  1083. containsKey: newConflictKeyError("name").Error(),
  1084. },
  1085. {
  1086. name: "more struct anonymous",
  1087. t: reflect.TypeOf(struct {
  1088. Value struct {
  1089. ParentSt
  1090. Name string
  1091. }
  1092. }{}),
  1093. ok: false,
  1094. containsKey: newConflictKeyError("value.name").Error(),
  1095. },
  1096. {
  1097. name: "map anonymous",
  1098. t: reflect.TypeOf(struct {
  1099. ParentSt
  1100. M string
  1101. }{}),
  1102. ok: false,
  1103. containsKey: newConflictKeyError("m").Error(),
  1104. },
  1105. {
  1106. name: "map more anonymous",
  1107. t: reflect.TypeOf(struct {
  1108. Value struct {
  1109. ParentSt
  1110. M string
  1111. }
  1112. }{}),
  1113. ok: false,
  1114. containsKey: newConflictKeyError("value.m").Error(),
  1115. },
  1116. {
  1117. name: "struct slice anonymous",
  1118. t: reflect.TypeOf([]struct {
  1119. ParentSt
  1120. Name string
  1121. }{}),
  1122. ok: false,
  1123. containsKey: newConflictKeyError("name").Error(),
  1124. },
  1125. }
  1126. for _, tt := range tests {
  1127. t.Run(tt.name, func(t *testing.T) {
  1128. _, err := buildFieldsInfo(tt.t, "")
  1129. if tt.ok {
  1130. assert.NoError(t, err)
  1131. } else {
  1132. assert.Error(t, err)
  1133. assert.Equal(t, err.Error(), tt.containsKey)
  1134. }
  1135. })
  1136. }
  1137. }
  1138. func createTempFile(ext, text string) (string, error) {
  1139. tmpFile, err := os.CreateTemp(os.TempDir(), hash.Md5Hex([]byte(text))+"*"+ext)
  1140. if err != nil {
  1141. return "", err
  1142. }
  1143. if err := os.WriteFile(tmpFile.Name(), []byte(text), os.ModeTemporary); err != nil {
  1144. return "", err
  1145. }
  1146. filename := tmpFile.Name()
  1147. if err = tmpFile.Close(); err != nil {
  1148. return "", err
  1149. }
  1150. return filename, nil
  1151. }