選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 

459 行
12 KiB

  1. package check
  2. import (
  3. "fmt"
  4. "reflect"
  5. "regexp"
  6. )
  7. // -----------------------------------------------------------------------
  8. // CommentInterface and Commentf helper, to attach extra information to checks.
  9. type comment struct {
  10. format string
  11. args []interface{}
  12. }
  13. // Commentf returns an infomational value to use with Assert or Check calls.
  14. // If the checker test fails, the provided arguments will be passed to
  15. // fmt.Sprintf, and will be presented next to the logged failure.
  16. //
  17. // For example:
  18. //
  19. // c.Assert(v, Equals, 42, Commentf("Iteration #%d failed.", i))
  20. //
  21. // Note that if the comment is constant, a better option is to
  22. // simply use a normal comment right above or next to the line, as
  23. // it will also get printed with any errors:
  24. //
  25. // c.Assert(l, Equals, 8192) // Ensure buffer size is correct (bug #123)
  26. //
  27. func Commentf(format string, args ...interface{}) CommentInterface {
  28. return &comment{format, args}
  29. }
  30. // CommentInterface must be implemented by types that attach extra
  31. // information to failed checks. See the Commentf function for details.
  32. type CommentInterface interface {
  33. CheckCommentString() string
  34. }
  35. func (c *comment) CheckCommentString() string {
  36. return fmt.Sprintf(c.format, c.args...)
  37. }
  38. // -----------------------------------------------------------------------
  39. // The Checker interface.
  40. // The Checker interface must be provided by checkers used with
  41. // the Assert and Check verification methods.
  42. type Checker interface {
  43. Info() *CheckerInfo
  44. Check(params []interface{}, names []string) (result bool, error string)
  45. }
  46. // See the Checker interface.
  47. type CheckerInfo struct {
  48. Name string
  49. Params []string
  50. }
  51. func (info *CheckerInfo) Info() *CheckerInfo {
  52. return info
  53. }
  54. // -----------------------------------------------------------------------
  55. // Not checker logic inverter.
  56. // The Not checker inverts the logic of the provided checker. The
  57. // resulting checker will succeed where the original one failed, and
  58. // vice-versa.
  59. //
  60. // For example:
  61. //
  62. // c.Assert(a, Not(Equals), b)
  63. //
  64. func Not(checker Checker) Checker {
  65. return &notChecker{checker}
  66. }
  67. type notChecker struct {
  68. sub Checker
  69. }
  70. func (checker *notChecker) Info() *CheckerInfo {
  71. info := *checker.sub.Info()
  72. info.Name = "Not(" + info.Name + ")"
  73. return &info
  74. }
  75. func (checker *notChecker) Check(params []interface{}, names []string) (result bool, error string) {
  76. result, error = checker.sub.Check(params, names)
  77. result = !result
  78. return
  79. }
  80. // -----------------------------------------------------------------------
  81. // IsNil checker.
  82. type isNilChecker struct {
  83. *CheckerInfo
  84. }
  85. // The IsNil checker tests whether the obtained value is nil.
  86. //
  87. // For example:
  88. //
  89. // c.Assert(err, IsNil)
  90. //
  91. var IsNil Checker = &isNilChecker{
  92. &CheckerInfo{Name: "IsNil", Params: []string{"value"}},
  93. }
  94. func (checker *isNilChecker) Check(params []interface{}, names []string) (result bool, error string) {
  95. return isNil(params[0]), ""
  96. }
  97. func isNil(obtained interface{}) (result bool) {
  98. if obtained == nil {
  99. result = true
  100. } else {
  101. switch v := reflect.ValueOf(obtained); v.Kind() {
  102. case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
  103. return v.IsNil()
  104. }
  105. }
  106. return
  107. }
  108. // -----------------------------------------------------------------------
  109. // NotNil checker. Alias for Not(IsNil), since it's so common.
  110. type notNilChecker struct {
  111. *CheckerInfo
  112. }
  113. // The NotNil checker verifies that the obtained value is not nil.
  114. //
  115. // For example:
  116. //
  117. // c.Assert(iface, NotNil)
  118. //
  119. // This is an alias for Not(IsNil), made available since it's a
  120. // fairly common check.
  121. //
  122. var NotNil Checker = &notNilChecker{
  123. &CheckerInfo{Name: "NotNil", Params: []string{"value"}},
  124. }
  125. func (checker *notNilChecker) Check(params []interface{}, names []string) (result bool, error string) {
  126. return !isNil(params[0]), ""
  127. }
  128. // -----------------------------------------------------------------------
  129. // Equals checker.
  130. type equalsChecker struct {
  131. *CheckerInfo
  132. }
  133. // The Equals checker verifies that the obtained value is equal to
  134. // the expected value, according to usual Go semantics for ==.
  135. //
  136. // For example:
  137. //
  138. // c.Assert(value, Equals, 42)
  139. //
  140. var Equals Checker = &equalsChecker{
  141. &CheckerInfo{Name: "Equals", Params: []string{"obtained", "expected"}},
  142. }
  143. func (checker *equalsChecker) Check(params []interface{}, names []string) (result bool, error string) {
  144. defer func() {
  145. if v := recover(); v != nil {
  146. result = false
  147. error = fmt.Sprint(v)
  148. }
  149. }()
  150. return params[0] == params[1], ""
  151. }
  152. // -----------------------------------------------------------------------
  153. // DeepEquals checker.
  154. type deepEqualsChecker struct {
  155. *CheckerInfo
  156. }
  157. // The DeepEquals checker verifies that the obtained value is deep-equal to
  158. // the expected value. The check will work correctly even when facing
  159. // slices, interfaces, and values of different types (which always fail
  160. // the test).
  161. //
  162. // For example:
  163. //
  164. // c.Assert(value, DeepEquals, 42)
  165. // c.Assert(array, DeepEquals, []string{"hi", "there"})
  166. //
  167. var DeepEquals Checker = &deepEqualsChecker{
  168. &CheckerInfo{Name: "DeepEquals", Params: []string{"obtained", "expected"}},
  169. }
  170. func (checker *deepEqualsChecker) Check(params []interface{}, names []string) (result bool, error string) {
  171. return reflect.DeepEqual(params[0], params[1]), ""
  172. }
  173. // -----------------------------------------------------------------------
  174. // HasLen checker.
  175. type hasLenChecker struct {
  176. *CheckerInfo
  177. }
  178. // The HasLen checker verifies that the obtained value has the
  179. // provided length. In many cases this is superior to using Equals
  180. // in conjunction with the len function because in case the check
  181. // fails the value itself will be printed, instead of its length,
  182. // providing more details for figuring the problem.
  183. //
  184. // For example:
  185. //
  186. // c.Assert(list, HasLen, 5)
  187. //
  188. var HasLen Checker = &hasLenChecker{
  189. &CheckerInfo{Name: "HasLen", Params: []string{"obtained", "n"}},
  190. }
  191. func (checker *hasLenChecker) Check(params []interface{}, names []string) (result bool, error string) {
  192. n, ok := params[1].(int)
  193. if !ok {
  194. return false, "n must be an int"
  195. }
  196. value := reflect.ValueOf(params[0])
  197. switch value.Kind() {
  198. case reflect.Map, reflect.Array, reflect.Slice, reflect.Chan, reflect.String:
  199. default:
  200. return false, "obtained value type has no length"
  201. }
  202. return value.Len() == n, ""
  203. }
  204. // -----------------------------------------------------------------------
  205. // ErrorMatches checker.
  206. type errorMatchesChecker struct {
  207. *CheckerInfo
  208. }
  209. // The ErrorMatches checker verifies that the error value
  210. // is non nil and matches the regular expression provided.
  211. //
  212. // For example:
  213. //
  214. // c.Assert(err, ErrorMatches, "perm.*denied")
  215. //
  216. var ErrorMatches Checker = errorMatchesChecker{
  217. &CheckerInfo{Name: "ErrorMatches", Params: []string{"value", "regex"}},
  218. }
  219. func (checker errorMatchesChecker) Check(params []interface{}, names []string) (result bool, errStr string) {
  220. if params[0] == nil {
  221. return false, "Error value is nil"
  222. }
  223. err, ok := params[0].(error)
  224. if !ok {
  225. return false, "Value is not an error"
  226. }
  227. params[0] = err.Error()
  228. names[0] = "error"
  229. return matches(params[0], params[1])
  230. }
  231. // -----------------------------------------------------------------------
  232. // Matches checker.
  233. type matchesChecker struct {
  234. *CheckerInfo
  235. }
  236. // The Matches checker verifies that the string provided as the obtained
  237. // value (or the string resulting from obtained.String()) matches the
  238. // regular expression provided.
  239. //
  240. // For example:
  241. //
  242. // c.Assert(err, Matches, "perm.*denied")
  243. //
  244. var Matches Checker = &matchesChecker{
  245. &CheckerInfo{Name: "Matches", Params: []string{"value", "regex"}},
  246. }
  247. func (checker *matchesChecker) Check(params []interface{}, names []string) (result bool, error string) {
  248. return matches(params[0], params[1])
  249. }
  250. func matches(value, regex interface{}) (result bool, error string) {
  251. reStr, ok := regex.(string)
  252. if !ok {
  253. return false, "Regex must be a string"
  254. }
  255. valueStr, valueIsStr := value.(string)
  256. if !valueIsStr {
  257. if valueWithStr, valueHasStr := value.(fmt.Stringer); valueHasStr {
  258. valueStr, valueIsStr = valueWithStr.String(), true
  259. }
  260. }
  261. if valueIsStr {
  262. matches, err := regexp.MatchString("^"+reStr+"$", valueStr)
  263. if err != nil {
  264. return false, "Can't compile regex: " + err.Error()
  265. }
  266. return matches, ""
  267. }
  268. return false, "Obtained value is not a string and has no .String()"
  269. }
  270. // -----------------------------------------------------------------------
  271. // Panics checker.
  272. type panicsChecker struct {
  273. *CheckerInfo
  274. }
  275. // The Panics checker verifies that calling the provided zero-argument
  276. // function will cause a panic which is deep-equal to the provided value.
  277. //
  278. // For example:
  279. //
  280. // c.Assert(func() { f(1, 2) }, Panics, &SomeErrorType{"BOOM"}).
  281. //
  282. //
  283. var Panics Checker = &panicsChecker{
  284. &CheckerInfo{Name: "Panics", Params: []string{"function", "expected"}},
  285. }
  286. func (checker *panicsChecker) Check(params []interface{}, names []string) (result bool, error string) {
  287. f := reflect.ValueOf(params[0])
  288. if f.Kind() != reflect.Func || f.Type().NumIn() != 0 {
  289. return false, "Function must take zero arguments"
  290. }
  291. defer func() {
  292. // If the function has not panicked, then don't do the check.
  293. if error != "" {
  294. return
  295. }
  296. params[0] = recover()
  297. names[0] = "panic"
  298. result = reflect.DeepEqual(params[0], params[1])
  299. }()
  300. f.Call(nil)
  301. return false, "Function has not panicked"
  302. }
  303. type panicMatchesChecker struct {
  304. *CheckerInfo
  305. }
  306. // The PanicMatches checker verifies that calling the provided zero-argument
  307. // function will cause a panic with an error value matching
  308. // the regular expression provided.
  309. //
  310. // For example:
  311. //
  312. // c.Assert(func() { f(1, 2) }, PanicMatches, `open.*: no such file or directory`).
  313. //
  314. //
  315. var PanicMatches Checker = &panicMatchesChecker{
  316. &CheckerInfo{Name: "PanicMatches", Params: []string{"function", "expected"}},
  317. }
  318. func (checker *panicMatchesChecker) Check(params []interface{}, names []string) (result bool, errmsg string) {
  319. f := reflect.ValueOf(params[0])
  320. if f.Kind() != reflect.Func || f.Type().NumIn() != 0 {
  321. return false, "Function must take zero arguments"
  322. }
  323. defer func() {
  324. // If the function has not panicked, then don't do the check.
  325. if errmsg != "" {
  326. return
  327. }
  328. obtained := recover()
  329. names[0] = "panic"
  330. if e, ok := obtained.(error); ok {
  331. params[0] = e.Error()
  332. } else if _, ok := obtained.(string); ok {
  333. params[0] = obtained
  334. } else {
  335. errmsg = "Panic value is not a string or an error"
  336. return
  337. }
  338. result, errmsg = matches(params[0], params[1])
  339. }()
  340. f.Call(nil)
  341. return false, "Function has not panicked"
  342. }
  343. // -----------------------------------------------------------------------
  344. // FitsTypeOf checker.
  345. type fitsTypeChecker struct {
  346. *CheckerInfo
  347. }
  348. // The FitsTypeOf checker verifies that the obtained value is
  349. // assignable to a variable with the same type as the provided
  350. // sample value.
  351. //
  352. // For example:
  353. //
  354. // c.Assert(value, FitsTypeOf, int64(0))
  355. // c.Assert(value, FitsTypeOf, os.Error(nil))
  356. //
  357. var FitsTypeOf Checker = &fitsTypeChecker{
  358. &CheckerInfo{Name: "FitsTypeOf", Params: []string{"obtained", "sample"}},
  359. }
  360. func (checker *fitsTypeChecker) Check(params []interface{}, names []string) (result bool, error string) {
  361. obtained := reflect.ValueOf(params[0])
  362. sample := reflect.ValueOf(params[1])
  363. if !obtained.IsValid() {
  364. return false, ""
  365. }
  366. if !sample.IsValid() {
  367. return false, "Invalid sample value"
  368. }
  369. return obtained.Type().AssignableTo(sample.Type()), ""
  370. }
  371. // -----------------------------------------------------------------------
  372. // Implements checker.
  373. type implementsChecker struct {
  374. *CheckerInfo
  375. }
  376. // The Implements checker verifies that the obtained value
  377. // implements the interface specified via a pointer to an interface
  378. // variable.
  379. //
  380. // For example:
  381. //
  382. // var e os.Error
  383. // c.Assert(err, Implements, &e)
  384. //
  385. var Implements Checker = &implementsChecker{
  386. &CheckerInfo{Name: "Implements", Params: []string{"obtained", "ifaceptr"}},
  387. }
  388. func (checker *implementsChecker) Check(params []interface{}, names []string) (result bool, error string) {
  389. obtained := reflect.ValueOf(params[0])
  390. ifaceptr := reflect.ValueOf(params[1])
  391. if !obtained.IsValid() {
  392. return false, ""
  393. }
  394. if !ifaceptr.IsValid() || ifaceptr.Kind() != reflect.Ptr || ifaceptr.Elem().Kind() != reflect.Interface {
  395. return false, "ifaceptr should be a pointer to an interface variable"
  396. }
  397. return obtained.Type().Implements(ifaceptr.Elem().Type()), ""
  398. }