importer_test.go 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. package exchange_test
  2. import (
  3. "errors"
  4. "fmt"
  5. "io/ioutil"
  6. "strings"
  7. "testing"
  8. "time"
  9. "github.com/qor5/x/exchange"
  10. "github.com/stretchr/testify/assert"
  11. )
  12. func TestImport(t *testing.T) {
  13. for _, c := range []struct {
  14. name string
  15. metas []*exchange.Meta
  16. validators []func(metaValues exchange.MetaValues) error
  17. csvContent string
  18. expectRecords []*TestExchangeModel
  19. expectError error
  20. }{
  21. {
  22. name: "normal",
  23. metas: []*exchange.Meta{
  24. exchange.NewMeta("ID").PrimaryKey(true),
  25. exchange.NewMeta("Name").Header("Nameeee"),
  26. exchange.NewMeta("Age"),
  27. exchange.NewMeta("Birth").Setter(func(record interface{}, value string, metaValues exchange.MetaValues) error {
  28. r := record.(*TestExchangeModel)
  29. if value == "" {
  30. r.Birth = nil
  31. return nil
  32. }
  33. t, err := time.ParseInLocation("2006-01-02", value, time.UTC)
  34. if err != nil {
  35. return err
  36. }
  37. r.Birth = &t
  38. return nil
  39. }),
  40. },
  41. csvContent: `ID,Nameeee,Age,Birth
  42. 1,Tom,6,1939-01-01
  43. 2,Jerry,5,1940-02-10
  44. `,
  45. expectRecords: []*TestExchangeModel{
  46. {
  47. ID: 1,
  48. Name: "Tom",
  49. Age: ptrInt(6),
  50. Birth: ptrTime(time.Date(1939, 1, 1, 0, 0, 0, 0, time.UTC)),
  51. },
  52. {
  53. ID: 2,
  54. Name: "Jerry",
  55. Age: ptrInt(5),
  56. Birth: ptrTime(time.Date(1940, 2, 10, 0, 0, 0, 0, time.UTC)),
  57. },
  58. },
  59. expectError: nil,
  60. },
  61. {
  62. name: "has extra columns",
  63. metas: []*exchange.Meta{
  64. exchange.NewMeta("ID").PrimaryKey(true),
  65. exchange.NewMeta("Name").Header("Nameeee"),
  66. exchange.NewMeta("Age"),
  67. },
  68. csvContent: `ID,Nameeee,Name2,Age,Birth,Hobby
  69. 1,Tom,Tomey,6,1939-01-01,sleep
  70. `,
  71. expectRecords: []*TestExchangeModel{
  72. {
  73. ID: 1,
  74. Name: "Tom",
  75. Age: ptrInt(6),
  76. },
  77. },
  78. expectError: nil,
  79. },
  80. {
  81. name: "empty value",
  82. metas: []*exchange.Meta{
  83. exchange.NewMeta("ID").PrimaryKey(true),
  84. exchange.NewMeta("Name").Header("Nameeee"),
  85. exchange.NewMeta("Age"),
  86. },
  87. csvContent: `ID,Nameeee,Age,Birth
  88. 1,,,1939-01-01
  89. 2,Jerry,5,1940-02-10
  90. `,
  91. expectRecords: []*TestExchangeModel{
  92. {
  93. ID: 1,
  94. Name: "",
  95. Age: nil,
  96. },
  97. {
  98. ID: 2,
  99. Name: "Jerry",
  100. Age: ptrInt(5),
  101. },
  102. },
  103. expectError: nil,
  104. },
  105. {
  106. name: "missing columns",
  107. metas: []*exchange.Meta{
  108. exchange.NewMeta("ID").PrimaryKey(true),
  109. exchange.NewMeta("Name").Header("Nameeee"),
  110. exchange.NewMeta("Age"),
  111. },
  112. csvContent: `ID,Nameeee
  113. 1,Tom
  114. `,
  115. expectRecords: nil,
  116. expectError: errors.New("column Age not found"),
  117. },
  118. {
  119. name: "validator error",
  120. metas: []*exchange.Meta{
  121. exchange.NewMeta("ID").PrimaryKey(true),
  122. exchange.NewMeta("Name").Header("Nameeee"),
  123. },
  124. validators: []func(metaValues exchange.MetaValues) error{
  125. func(ms exchange.MetaValues) error {
  126. v := ms.Get("Name")
  127. if v == "" {
  128. return errors.New("name cannot be empty")
  129. }
  130. return nil
  131. },
  132. },
  133. csvContent: `ID,Nameeee,Age,Birth
  134. 1,Tom,6,1939-01-01
  135. 2,,5,1940-02-10
  136. `,
  137. expectRecords: nil,
  138. expectError: fmt.Errorf("name cannot be empty"),
  139. },
  140. } {
  141. initTables()
  142. r, err := exchange.NewCSVReader(ioutil.NopCloser(strings.NewReader(c.csvContent)))
  143. assert.NoError(t, err, c.name)
  144. err = exchange.NewImporter(&TestExchangeModel{}).
  145. Metas(c.metas...).
  146. Validators(c.validators...).
  147. Exec(db, r)
  148. if err != nil {
  149. assert.Equal(t, c.expectError, err, c.name)
  150. continue
  151. }
  152. var records []*TestExchangeModel
  153. err = db.Order("id asc").Find(&records).Error
  154. assert.NoError(t, err, c.name)
  155. assert.Equal(t, c.expectRecords, records, c.name)
  156. }
  157. }
  158. func TestReImport(t *testing.T) {
  159. initTables()
  160. var err error
  161. importer := exchange.NewImporter(&TestExchangeModel{}).
  162. Metas(
  163. exchange.NewMeta("ID").PrimaryKey(true),
  164. exchange.NewMeta("Name"),
  165. exchange.NewMeta("Appender").Setter(func(record interface{}, value string, metaValues exchange.MetaValues) error {
  166. r := record.(*TestExchangeModel)
  167. r.Appender += value
  168. return nil
  169. }),
  170. )
  171. // 1st import
  172. r, err := exchange.NewCSVReader(ioutil.NopCloser(strings.NewReader(`ID,Name,Appender
  173. 1,Tom,aa
  174. 2,Jerry,bb
  175. `)))
  176. assert.NoError(t, err)
  177. err = importer.Exec(db, r)
  178. assert.NoError(t, err)
  179. // 2nd import
  180. r, err = exchange.NewCSVReader(ioutil.NopCloser(strings.NewReader(`ID,Name,Appender
  181. 1,Tomey,AA
  182. 2,,BB
  183. 3,Spike,cc
  184. `)))
  185. assert.NoError(t, err)
  186. err = importer.Exec(db, r)
  187. assert.NoError(t, err)
  188. // 3nd import
  189. r, err = exchange.NewCSVReader(ioutil.NopCloser(strings.NewReader(`ID,Name,Appender
  190. 1,Tomey2,aa
  191. `)))
  192. assert.NoError(t, err)
  193. err = importer.Exec(db, r)
  194. assert.NoError(t, err)
  195. var records []*TestExchangeModel
  196. err = db.Order("id asc").Find(&records).Error
  197. assert.NoError(t, err)
  198. assert.Equal(t, []*TestExchangeModel{
  199. {
  200. ID: 1,
  201. Name: "Tomey2",
  202. Appender: "aaAAaa",
  203. },
  204. {
  205. ID: 2,
  206. Name: "",
  207. Appender: "bbBB",
  208. },
  209. {
  210. ID: 3,
  211. Name: "Spike",
  212. Appender: "cc",
  213. },
  214. }, records)
  215. }
  216. func TestEmptyPrimaryKeyValue(t *testing.T) {
  217. initTables()
  218. var err error
  219. importer := exchange.NewImporter(&TestExchangeModel{}).
  220. Metas(
  221. exchange.NewMeta("ID").PrimaryKey(true),
  222. exchange.NewMeta("Name"),
  223. )
  224. // 1st import
  225. r, err := exchange.NewCSVReader(ioutil.NopCloser(strings.NewReader(`ID,Name
  226. ,Tom
  227. ,Jerry
  228. `)))
  229. assert.NoError(t, err)
  230. err = importer.Exec(db, r)
  231. assert.NoError(t, err)
  232. records := make([]*TestExchangeModel, 0)
  233. err = db.Order("id asc").Find(&records).Error
  234. assert.NoError(t, err)
  235. assert.Equal(t, []*TestExchangeModel{
  236. {
  237. ID: 1,
  238. Name: "Tom",
  239. },
  240. {
  241. ID: 2,
  242. Name: "Jerry",
  243. },
  244. }, records)
  245. // 2nd import
  246. r, err = exchange.NewCSVReader(ioutil.NopCloser(strings.NewReader(`ID,Name
  247. 1,Tomey
  248. ,Jerry
  249. ,Spike
  250. `)))
  251. assert.NoError(t, err)
  252. err = importer.Exec(db, r)
  253. assert.NoError(t, err)
  254. records = make([]*TestExchangeModel, 0)
  255. err = db.Order("id asc").Find(&records).Error
  256. assert.NoError(t, err)
  257. assert.Equal(t, []*TestExchangeModel{
  258. {
  259. ID: 1,
  260. Name: "Tomey",
  261. },
  262. {
  263. ID: 2,
  264. Name: "Jerry",
  265. },
  266. {
  267. ID: 3,
  268. Name: "Jerry",
  269. },
  270. {
  271. ID: 4,
  272. Name: "Spike",
  273. },
  274. }, records)
  275. }
  276. func TestNoPrimaryKeyMeta(t *testing.T) {
  277. initTables()
  278. var err error
  279. importer := exchange.NewImporter(&TestExchangeModel{}).
  280. Metas(
  281. exchange.NewMeta("Name"),
  282. )
  283. // 1st import
  284. r, err := exchange.NewCSVReader(ioutil.NopCloser(strings.NewReader(`Name
  285. Tom
  286. Jerry
  287. `)))
  288. assert.NoError(t, err)
  289. err = importer.Exec(db, r)
  290. assert.NoError(t, err)
  291. records := make([]*TestExchangeModel, 0)
  292. err = db.Order("id asc").Find(&records).Error
  293. assert.NoError(t, err)
  294. assert.Equal(t, []*TestExchangeModel{
  295. {
  296. ID: 1,
  297. Name: "Tom",
  298. },
  299. {
  300. ID: 2,
  301. Name: "Jerry",
  302. },
  303. }, records)
  304. // 2nd import
  305. r, err = exchange.NewCSVReader(ioutil.NopCloser(strings.NewReader(`Name
  306. Tom
  307. Jerry
  308. `)))
  309. assert.NoError(t, err)
  310. err = importer.Exec(db, r)
  311. assert.NoError(t, err)
  312. records = make([]*TestExchangeModel, 0)
  313. err = db.Order("id asc").Find(&records).Error
  314. assert.NoError(t, err)
  315. assert.Equal(t, []*TestExchangeModel{
  316. {
  317. ID: 1,
  318. Name: "Tom",
  319. },
  320. {
  321. ID: 2,
  322. Name: "Jerry",
  323. },
  324. {
  325. ID: 3,
  326. Name: "Tom",
  327. },
  328. {
  329. ID: 4,
  330. Name: "Jerry",
  331. },
  332. }, records)
  333. }
  334. func TestCompositePrimaryKey(t *testing.T) {
  335. initTables()
  336. var err error
  337. // 1st import
  338. importer := exchange.NewImporter(&TestExchangeCompositePrimaryKeyModel{}).Metas(
  339. exchange.NewMeta("ID").PrimaryKey(true),
  340. exchange.NewMeta("Name").Header("Name").PrimaryKey(true),
  341. exchange.NewMeta("Age"),
  342. exchange.NewMeta("Appender").Setter(func(record interface{}, value string, metaValues exchange.MetaValues) error {
  343. r := record.(*TestExchangeCompositePrimaryKeyModel)
  344. r.Appender += value
  345. return nil
  346. }),
  347. )
  348. r, err := exchange.NewCSVReader(ioutil.NopCloser(strings.NewReader(`ID,Name,Age,Appender
  349. 1,Tom,6,aa
  350. 1,Tom2,16,bb
  351. 2,Jerry,5,cc
  352. `)))
  353. assert.NoError(t, err)
  354. err = importer.Exec(db, r)
  355. assert.NoError(t, err)
  356. records := []*TestExchangeCompositePrimaryKeyModel{}
  357. err = db.Order("id asc, name asc").Find(&records).Error
  358. assert.NoError(t, err)
  359. assert.Equal(t, []*TestExchangeCompositePrimaryKeyModel{
  360. {
  361. ID: 1,
  362. Name: "Tom",
  363. Age: ptrInt(6),
  364. Appender: "aa",
  365. },
  366. {
  367. ID: 1,
  368. Name: "Tom2",
  369. Age: ptrInt(16),
  370. Appender: "bb",
  371. },
  372. {
  373. ID: 2,
  374. Name: "Jerry",
  375. Age: ptrInt(5),
  376. Appender: "cc",
  377. },
  378. }, records)
  379. // 2nd import
  380. r, err = exchange.NewCSVReader(ioutil.NopCloser(strings.NewReader(`ID,Name,Age,Appender
  381. 1,Tom,7,AA
  382. 1,Tom2,16,BB
  383. 2,Jerry2,6,dd
  384. `)))
  385. assert.NoError(t, err)
  386. err = importer.Exec(db, r)
  387. assert.NoError(t, err)
  388. records = []*TestExchangeCompositePrimaryKeyModel{}
  389. err = db.Order("id asc, name asc").Find(&records).Error
  390. assert.NoError(t, err)
  391. assert.Equal(t, []*TestExchangeCompositePrimaryKeyModel{
  392. {
  393. ID: 1,
  394. Name: "Tom",
  395. Age: ptrInt(7),
  396. Appender: "aaAA",
  397. },
  398. {
  399. ID: 1,
  400. Name: "Tom2",
  401. Age: ptrInt(16),
  402. Appender: "bbBB",
  403. },
  404. {
  405. ID: 2,
  406. Name: "Jerry",
  407. Age: ptrInt(5),
  408. Appender: "cc",
  409. },
  410. {
  411. ID: 2,
  412. Name: "Jerry2",
  413. Age: ptrInt(6),
  414. Appender: "dd",
  415. },
  416. }, records)
  417. }
  418. func TestNoAffectOnOldData(t *testing.T) {
  419. initTables()
  420. var err error
  421. db.Create(&TestExchangeModel{
  422. ID: 1,
  423. Name: "Tom",
  424. Age: ptrInt(5),
  425. })
  426. importer := exchange.NewImporter(&TestExchangeModel{}).
  427. Metas(
  428. exchange.NewMeta("ID").PrimaryKey(true),
  429. exchange.NewMeta("Name"),
  430. )
  431. // 1st import
  432. r, err := exchange.NewCSVReader(ioutil.NopCloser(strings.NewReader(`ID,Name
  433. 1,Tom2
  434. `)))
  435. assert.NoError(t, err)
  436. err = importer.Exec(db, r)
  437. assert.NoError(t, err)
  438. records := make([]*TestExchangeModel, 0)
  439. err = db.Order("id asc").Find(&records).Error
  440. assert.NoError(t, err)
  441. assert.Equal(t, []*TestExchangeModel{
  442. {
  443. ID: 1,
  444. Name: "Tom2",
  445. Age: ptrInt(5),
  446. },
  447. }, records)
  448. }