internal: improve use of detrand in descfmt and errors

Use a non-breaking space instead of two spaces to vary the output.
This keeps the mutated version aesthetically similar to the normal one.

Change-Id: Ib4ade2795004fe5b30e454e7e533e5a0e3a9ffa2
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/194157
Reviewed-by: Herbie Ong <herbie@google.com>
This commit is contained in:
Joe Tsai 2019-09-07 12:06:05 -07:00
parent 9e356dea53
commit 27af11f144
3 changed files with 25 additions and 29 deletions

View File

@ -43,7 +43,7 @@ func formatListOpt(vs list, isRoot, allowMulti bool) string {
case pref.Descriptor:
name = reflect.ValueOf(vs).MethodByName("Get").Type().Out(0).Name() + "s"
}
start, end = name+randomSpace()+"{", "}"
start, end = name+"{", "}"
}
var ss []string
@ -123,7 +123,7 @@ func formatDescOpt(t pref.Descriptor, isRoot, allowMulti bool) string {
start, end := "{", "}"
if isRoot {
start = rt.Name() + randomSpace() + "{"
start = rt.Name() + "{"
}
_, isFile := t.(pref.FileDescriptor)
@ -269,7 +269,7 @@ func (rs *records) Join() string {
// In single line mode, simply join all records with commas.
if !rs.allowMulti {
for _, r := range rs.recs {
ss = append(ss, r[0]+": "+r[1])
ss = append(ss, r[0]+formatColon(0)+r[1])
}
return joinStrings(ss, false)
}
@ -278,15 +278,14 @@ func (rs *records) Join() string {
var maxLen int
flush := func(i int) {
for _, r := range rs.recs[len(ss):i] {
padding := strings.Repeat(" ", maxLen-len(r[0]))
ss = append(ss, r[0]+": "+padding+r[1])
ss = append(ss, r[0]+formatColon(maxLen-len(r[0]))+r[1])
}
maxLen = 0
}
for i, r := range rs.recs {
if isMulti := strings.Contains(r[1], "\n"); isMulti {
flush(i)
ss = append(ss, r[0]+": "+strings.Join(strings.Split(r[1], "\n"), "\n\t"))
ss = append(ss, r[0]+formatColon(0)+strings.Join(strings.Split(r[1], "\n"), "\n\t"))
} else if maxLen < len(r[0]) {
maxLen = len(r[0])
}
@ -295,6 +294,17 @@ func (rs *records) Join() string {
return joinStrings(ss, true)
}
func formatColon(padding int) string {
// Deliberately introduce instability into the debug output to
// discourage users from performing string comparisons.
// This provides us flexibility to change the output in the future.
if detrand.Bool() {
return ":" + strings.Repeat(" ", 1+padding) // use non-breaking spaces (U+00a0)
} else {
return ":" + strings.Repeat(" ", 1+padding) // use regular spaces (U+0020)
}
}
func joinStrings(ss []string, isMulti bool) string {
if len(ss) == 0 {
return ""
@ -304,12 +314,3 @@ func joinStrings(ss []string, isMulti bool) string {
}
return strings.Join(ss, ", ")
}
// randomSpace randomly returns a string that is either empty or a single space.
// This is done deliberately to ensure that the output is slightly non-stable.
//
// These makes it harder for people to depend on the debug string as stable
// and provides us the flexibility to make changes.
func randomSpace() string {
return " "[:detrand.Intn(2)]
}

View File

@ -18,24 +18,16 @@ import (
// Disable disables detrand such that all functions returns the zero value.
// This function is not concurrent-safe and must be called during program init.
func Disable() {
binHash = 0
randSeed = 0
}
// Bool returns a deterministically random boolean.
func Bool() bool {
return binHash%2 == 1
return randSeed%2 == 1
}
// Intn returns a deterministically random integer within [0,n).
func Intn(n int) int {
if n <= 0 {
panic("invalid argument to Intn")
}
return int(binHash % uint64(n))
}
// binHash is a best-effort at an approximate hash of the Go binary.
var binHash = binaryHash()
// randSeed is a best-effort at an approximate hash of the Go binary.
var randSeed = binaryHash()
func binaryHash() uint64 {
// Open the Go binary.

View File

@ -25,10 +25,13 @@ func New(f string, x ...interface{}) error {
type prefixError struct{ s string }
var prefix = func() string {
// Deliberately introduce instability into the error message string to
// discourage users from performing error string comparisons.
if detrand.Bool() {
return "proto: "
return "proto: " // use non-breaking spaces (U+00a0)
} else {
return "proto: " // use regular spaces (U+0020)
}
return "proto: "
}()
func (e *prefixError) Error() string {