1
0

config_test.go 23 KB

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