assert.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. package assert
  2. import (
  3. "bytes"
  4. "fmt"
  5. "runtime"
  6. "strings"
  7. "testing"
  8. )
  9. func On(t *testing.T) *Assert {
  10. return &Assert{
  11. t: t,
  12. }
  13. }
  14. type Assert struct {
  15. t *testing.T
  16. }
  17. func (this *Assert) Fail(message string) {
  18. fmt.Println(decorate(message))
  19. this.t.Fail()
  20. }
  21. func getCaller() (string, int) {
  22. stackLevel := 3
  23. for {
  24. _, file, line, ok := runtime.Caller(stackLevel)
  25. if strings.Contains(file, "assert") {
  26. stackLevel++
  27. } else {
  28. if ok {
  29. // Truncate file name at last file name separator.
  30. if index := strings.LastIndex(file, "/"); index >= 0 {
  31. file = file[index+1:]
  32. } else if index = strings.LastIndex(file, "\\"); index >= 0 {
  33. file = file[index+1:]
  34. }
  35. } else {
  36. file = "???"
  37. line = 1
  38. }
  39. return file, line
  40. }
  41. }
  42. }
  43. // decorate prefixes the string with the file and line of the call site
  44. // and inserts the final newline if needed and indentation tabs for formatting.
  45. func decorate(s string) string {
  46. file, line := getCaller()
  47. buf := new(bytes.Buffer)
  48. // Every line is indented at least one tab.
  49. buf.WriteString(" ")
  50. fmt.Fprintf(buf, "%s:%d: ", file, line)
  51. lines := strings.Split(s, "\n")
  52. if l := len(lines); l > 1 && lines[l-1] == "" {
  53. lines = lines[:l-1]
  54. }
  55. for i, line := range lines {
  56. if i > 0 {
  57. // Second and subsequent lines are indented an extra tab.
  58. buf.WriteString("\n\t\t")
  59. }
  60. buf.WriteString(line)
  61. }
  62. buf.WriteByte('\n')
  63. return buf.String()
  64. }