1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
15 // matcher sanitizes, uniques, and filters names of subtests and subbenchmarks.
18 matchFunc
func(pat
, str
string) (bool, error
)
21 subNames
map[string]int64
24 // TODO: fix test_main to avoid race and improve caching, also allowing to
25 // eliminate this Mutex.
26 var matchMutex sync
.Mutex
28 func newMatcher(matchString
func(pat
, str
string) (bool, error
), patterns
, name
string) *matcher
{
31 filter
= splitRegexp(patterns
)
32 for i
, s
:= range filter
{
33 filter
[i
] = rewrite(s
)
35 // Verify filters before doing any processing.
36 for i
, s
:= range filter
{
37 if _
, err
:= matchString(s
, "non-empty"); err
!= nil {
38 fmt
.Fprintf(os
.Stderr
, "testing: invalid regexp for element %d of %s (%q): %s\n", i
, name
, s
, err
)
45 matchFunc
: matchString
,
46 subNames
: map[string]int64{},
50 func (m
*matcher
) fullName(c
*common
, subname
string) (name
string, ok
, partial
bool) {
56 if c
!= nil && c
.level
> 0 {
57 name
= m
.unique(c
.name
, rewrite(subname
))
61 defer matchMutex
.Unlock()
63 // We check the full array of paths each time to allow for the case that
64 // a pattern contains a '/'.
65 elem
:= strings
.Split(name
, "/")
66 for i
, s
:= range elem
{
67 if i
>= len(m
.filter
) {
70 if ok
, _
:= m
.matchFunc(m
.filter
[i
], s
); !ok
{
71 return name
, false, false
74 return name
, true, len(elem
) < len(m
.filter
)
77 func splitRegexp(s
string) []string {
78 a
:= make([]string, 0, strings
.Count(s
, "/"))
81 for i
:= 0; i
< len(s
); {
86 if cs
--; cs
< 0 { // An unmatched ']' is legal.
100 if cs
== 0 && cp
== 0 {
112 // unique creates a unique name for the given parent and subname by affixing it
113 // with one ore more counts, if necessary.
114 func (m
*matcher
) unique(parent
, subname
string) string {
115 name
:= fmt
.Sprintf("%s/%s", parent
, subname
)
116 empty
:= subname
== ""
118 next
, exists
:= m
.subNames
[name
]
119 if !empty
&& !exists
{
120 m
.subNames
[name
] = 1 // next count is 1
123 // Name was already used. We increment with the count and append a
124 // string with the count.
125 m
.subNames
[name
] = next
+ 1
127 // Add a count to guarantee uniqueness.
128 name
= fmt
.Sprintf("%s#%02d", name
, next
)
133 // rewrite rewrites a subname to having only printable characters and no white
135 func rewrite(s
string) string {
137 for _
, r
:= range s
{
141 case !strconv
.IsPrint(r
):
142 s
:= strconv
.QuoteRune(r
)
143 b
= append(b
, s
[1:len(s
)-1]...)
145 b
= append(b
, string(r
)...)
151 func isSpace(r rune
) bool {
154 // Note: not the same as Unicode Z class.
155 case '\t', '\n', '\v', '\f', '\r', ' ', 0x85, 0xA0, 0x1680:
163 case 0x2028, 0x2029, 0x202f, 0x205f, 0x3000: