callbacks_test.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. package tests_test
  2. import (
  3. "fmt"
  4. "reflect"
  5. "runtime"
  6. "strings"
  7. "testing"
  8. "github.com/jinzhu/gorm"
  9. )
  10. func assertCallbacks(v interface{}, fnames []string) (result bool, msg string) {
  11. var (
  12. got []string
  13. funcs = reflect.ValueOf(v).Elem().FieldByName("fns")
  14. )
  15. for i := 0; i < funcs.Len(); i++ {
  16. got = append(got, getFuncName(funcs.Index(i)))
  17. }
  18. return fmt.Sprint(got) == fmt.Sprint(fnames), fmt.Sprintf("expects %v, got %v", fnames, got)
  19. }
  20. func getFuncName(fc interface{}) string {
  21. reflectValue, ok := fc.(reflect.Value)
  22. if !ok {
  23. reflectValue = reflect.ValueOf(fc)
  24. }
  25. fnames := strings.Split(runtime.FuncForPC(reflectValue.Pointer()).Name(), ".")
  26. return fnames[len(fnames)-1]
  27. }
  28. func c1(*gorm.DB) {}
  29. func c2(*gorm.DB) {}
  30. func c3(*gorm.DB) {}
  31. func c4(*gorm.DB) {}
  32. func c5(*gorm.DB) {}
  33. func TestCallbacks(t *testing.T) {
  34. type callback struct {
  35. name string
  36. before string
  37. after string
  38. remove bool
  39. replace bool
  40. err string
  41. match func(*gorm.DB) bool
  42. h func(*gorm.DB)
  43. }
  44. datas := []struct {
  45. callbacks []callback
  46. err string
  47. results []string
  48. }{
  49. {
  50. callbacks: []callback{{h: c1}, {h: c2}, {h: c3}, {h: c4}, {h: c5}},
  51. results: []string{"c1", "c2", "c3", "c4", "c5"},
  52. },
  53. {
  54. callbacks: []callback{{h: c1}, {h: c2}, {h: c3}, {h: c4}, {h: c5, before: "c4"}},
  55. results: []string{"c1", "c2", "c3", "c5", "c4"},
  56. },
  57. {
  58. callbacks: []callback{{h: c1}, {h: c2}, {h: c3}, {h: c4, after: "c5"}, {h: c5}},
  59. results: []string{"c1", "c2", "c3", "c5", "c4"},
  60. },
  61. {
  62. callbacks: []callback{{h: c1}, {h: c2}, {h: c3}, {h: c4, after: "c5"}, {h: c5, before: "c4"}},
  63. results: []string{"c1", "c2", "c3", "c5", "c4"},
  64. },
  65. {
  66. callbacks: []callback{{h: c1}, {h: c2, before: "c4", after: "c5"}, {h: c3}, {h: c4}, {h: c5}},
  67. results: []string{"c1", "c5", "c2", "c3", "c4"},
  68. },
  69. {
  70. callbacks: []callback{{h: c1, after: "c3"}, {h: c2, before: "c4", after: "c5"}, {h: c3, before: "c5"}, {h: c4}, {h: c5}},
  71. results: []string{"c3", "c1", "c5", "c2", "c4"},
  72. },
  73. {
  74. callbacks: []callback{{h: c1, before: "c4", after: "c3"}, {h: c2, before: "c4", after: "c5"}, {h: c3, before: "c5"}, {h: c4}, {h: c5}},
  75. results: []string{"c3", "c1", "c5", "c2", "c4"},
  76. },
  77. {
  78. callbacks: []callback{{h: c1, before: "c3", after: "c4"}, {h: c2, before: "c4", after: "c5"}, {h: c3, before: "c5"}, {h: c4}, {h: c5}},
  79. err: "conflicting",
  80. },
  81. {
  82. callbacks: []callback{{h: c1}, {h: c2, before: "c4", after: "c5"}, {h: c3}, {h: c4}, {h: c5}, {h: c2, remove: true}},
  83. results: []string{"c1", "c5", "c3", "c4"},
  84. },
  85. {
  86. callbacks: []callback{{h: c1}, {name: "c", h: c2}, {h: c3}, {name: "c", h: c4, replace: true}},
  87. results: []string{"c1", "c4", "c3"},
  88. },
  89. }
  90. for idx, data := range datas {
  91. db, err := gorm.Open(nil, nil)
  92. callbacks := db.Callback()
  93. for _, c := range data.callbacks {
  94. var v interface{} = callbacks.Create()
  95. callMethod := func(s interface{}, name string, args ...interface{}) {
  96. var argValues []reflect.Value
  97. for _, arg := range args {
  98. argValues = append(argValues, reflect.ValueOf(arg))
  99. }
  100. results := reflect.ValueOf(s).MethodByName(name).Call(argValues)
  101. if len(results) > 0 {
  102. v = results[0].Interface()
  103. }
  104. }
  105. if c.name == "" {
  106. c.name = getFuncName(c.h)
  107. }
  108. if c.before != "" {
  109. callMethod(v, "Before", c.before)
  110. }
  111. if c.after != "" {
  112. callMethod(v, "After", c.after)
  113. }
  114. if c.match != nil {
  115. callMethod(v, "Match", c.match)
  116. }
  117. if c.remove {
  118. callMethod(v, "Remove", c.name)
  119. } else if c.replace {
  120. callMethod(v, "Replace", c.name, c.h)
  121. } else {
  122. callMethod(v, "Register", c.name, c.h)
  123. }
  124. if e, ok := v.(error); !ok || e != nil {
  125. err = e
  126. }
  127. }
  128. if len(data.err) > 0 && err == nil {
  129. t.Errorf("callbacks tests #%v should got error %v, but not", idx+1, data.err)
  130. } else if len(data.err) == 0 && err != nil {
  131. t.Errorf("callbacks tests #%v should not got error, but got %v", idx+1, err)
  132. }
  133. if ok, msg := assertCallbacks(callbacks.Create(), data.results); !ok {
  134. t.Errorf("callbacks tests #%v failed, got %v", idx+1, msg)
  135. }
  136. }
  137. }