internal/detrand: support disabling detrand

Since detrand is an internal package, we can safely provide a function
that can be called to disable its functionality for testing purposes.

Change-Id: I26383e12a5832eb5af01952898a4c73f627d7aa5
Reviewed-on: https://go-review.googlesource.com/c/151678
Reviewed-by: Herbie Ong <herbie@google.com>
diff --git a/internal/detrand/rand.go b/internal/detrand/rand.go
index c702f8f..f5d9eeb 100644
--- a/internal/detrand/rand.go
+++ b/internal/detrand/rand.go
@@ -15,9 +15,15 @@
 	"os"
 )
 
+// 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
+}
+
 // Bool returns a deterministically random boolean.
 func Bool() bool {
-	return binHash%2 == 0
+	return binHash%2 == 1
 }
 
 // Intn returns a deterministically random integer within [0,n).
diff --git a/internal/encoding/text/text_test.go b/internal/encoding/text/text_test.go
index 221d6ab..2f2d140 100644
--- a/internal/encoding/text/text_test.go
+++ b/internal/encoding/text/text_test.go
@@ -7,17 +7,20 @@
 import (
 	"fmt"
 	"math"
-	"regexp"
 	"strings"
 	"testing"
 	"unicode/utf8"
 
+	"github.com/golang/protobuf/v2/internal/detrand"
 	"github.com/golang/protobuf/v2/internal/flags"
 	"github.com/golang/protobuf/v2/reflect/protoreflect"
 	"github.com/google/go-cmp/cmp"
 	"github.com/google/go-cmp/cmp/cmpopts"
 )
 
+// Disable detrand to enable direct comparisons on outputs.
+func init() { detrand.Disable() }
+
 var S = fmt.Sprintf
 var V = ValueOf
 var ID = func(n protoreflect.Name) Value { return V(n) }
@@ -827,7 +830,7 @@
 				if err != nil {
 					t.Errorf("Marshal(): got %v, want nil error", err)
 				}
-				if removeRandomSpace(gotOut, false) != tt.wantOut {
+				if string(gotOut) != tt.wantOut {
 					t.Errorf("Marshal():\ngot:  %s\nwant: %s", gotOut, tt.wantOut)
 				}
 			}
@@ -836,7 +839,7 @@
 				if err != nil {
 					t.Errorf("Marshal(Bracket): got %v, want nil error", err)
 				}
-				if removeRandomSpace(gotOut, false) != tt.wantOutBracket {
+				if string(gotOut) != tt.wantOutBracket {
 					t.Errorf("Marshal(Bracket):\ngot:  %s\nwant: %s", gotOut, tt.wantOutBracket)
 				}
 			}
@@ -845,7 +848,7 @@
 				if err != nil {
 					t.Errorf("Marshal(ASCII): got %v, want nil error", err)
 				}
-				if removeRandomSpace(gotOut, false) != tt.wantOutASCII {
+				if string(gotOut) != tt.wantOutASCII {
 					t.Errorf("Marshal(ASCII):\ngot:  %s\nwant: %s", gotOut, tt.wantOutASCII)
 				}
 			}
@@ -854,24 +857,10 @@
 				if err != nil {
 					t.Errorf("Marshal(Indent): got %v, want nil error", err)
 				}
-				if removeRandomSpace(gotOut, true) != tt.wantOutIndent {
+				if string(gotOut) != tt.wantOutIndent {
 					t.Errorf("Marshal(Indent):\ngot:  %s\nwant: %s", gotOut, tt.wantOutIndent)
 				}
 			}
 		})
 	}
 }
-
-var expandedRE = regexp.MustCompile(":  +")
-
-// This works only for the test cases above.
-func removeRandomSpace(b []byte, useIndent bool) string {
-	s := string(b)
-	if useIndent {
-		return expandedRE.ReplaceAllString(s, ": ")
-	}
-	s = strings.Replace(s, "  ", " ", -1)
-	s = strings.Replace(s, " }", "}", -1)
-	s = strings.Replace(s, " >", ">", -1)
-	return strings.TrimRight(s, " ")
-}