specs.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. package spec
  2. import (
  3. "math/rand"
  4. "regexp"
  5. "sort"
  6. )
  7. type Specs struct {
  8. specs []*Spec
  9. hasProgrammaticFocus bool
  10. RegexScansFilePath bool
  11. }
  12. func NewSpecs(specs []*Spec) *Specs {
  13. return &Specs{
  14. specs: specs,
  15. }
  16. }
  17. func (e *Specs) Specs() []*Spec {
  18. return e.specs
  19. }
  20. func (e *Specs) HasProgrammaticFocus() bool {
  21. return e.hasProgrammaticFocus
  22. }
  23. func (e *Specs) Shuffle(r *rand.Rand) {
  24. sort.Sort(e)
  25. permutation := r.Perm(len(e.specs))
  26. shuffledSpecs := make([]*Spec, len(e.specs))
  27. for i, j := range permutation {
  28. shuffledSpecs[i] = e.specs[j]
  29. }
  30. e.specs = shuffledSpecs
  31. }
  32. func (e *Specs) ApplyFocus(description string, focusString string, skipString string) {
  33. if focusString == "" && skipString == "" {
  34. e.applyProgrammaticFocus()
  35. } else {
  36. e.applyRegExpFocusAndSkip(description, focusString, skipString)
  37. }
  38. }
  39. func (e *Specs) applyProgrammaticFocus() {
  40. e.hasProgrammaticFocus = false
  41. for _, spec := range e.specs {
  42. if spec.Focused() && !spec.Pending() {
  43. e.hasProgrammaticFocus = true
  44. break
  45. }
  46. }
  47. if e.hasProgrammaticFocus {
  48. for _, spec := range e.specs {
  49. if !spec.Focused() {
  50. spec.Skip()
  51. }
  52. }
  53. }
  54. }
  55. // toMatch returns a byte[] to be used by regex matchers. When adding new behaviours to the matching function,
  56. // this is the place which we append to.
  57. func (e *Specs) toMatch(description string, spec *Spec) []byte {
  58. if e.RegexScansFilePath {
  59. return []byte(
  60. description + " " +
  61. spec.ConcatenatedString() + " " +
  62. spec.subject.CodeLocation().FileName)
  63. } else {
  64. return []byte(
  65. description + " " +
  66. spec.ConcatenatedString())
  67. }
  68. }
  69. func (e *Specs) applyRegExpFocusAndSkip(description string, focusString string, skipString string) {
  70. for _, spec := range e.specs {
  71. matchesFocus := true
  72. matchesSkip := false
  73. toMatch := e.toMatch(description, spec)
  74. if focusString != "" {
  75. focusFilter := regexp.MustCompile(focusString)
  76. matchesFocus = focusFilter.Match([]byte(toMatch))
  77. }
  78. if skipString != "" {
  79. skipFilter := regexp.MustCompile(skipString)
  80. matchesSkip = skipFilter.Match([]byte(toMatch))
  81. }
  82. if !matchesFocus || matchesSkip {
  83. spec.Skip()
  84. }
  85. }
  86. }
  87. func (e *Specs) SkipMeasurements() {
  88. for _, spec := range e.specs {
  89. if spec.IsMeasurement() {
  90. spec.Skip()
  91. }
  92. }
  93. }
  94. //sort.Interface
  95. func (e *Specs) Len() int {
  96. return len(e.specs)
  97. }
  98. func (e *Specs) Less(i, j int) bool {
  99. return e.specs[i].ConcatenatedString() < e.specs[j].ConcatenatedString()
  100. }
  101. func (e *Specs) Swap(i, j int) {
  102. e.specs[i], e.specs[j] = e.specs[j], e.specs[i]
  103. }