diff --git a/grpcreplay/grpcreplay_test.go b/grpcreplay/grpcreplay_test.go index b7b8bd4..e4a5e61 100644 --- a/grpcreplay/grpcreplay_test.go +++ b/grpcreplay/grpcreplay_test.go @@ -703,5 +703,4 @@ func TestSetInitial(t *testing.T) { if got, want := rep.Initial(), initialState; !bytes.Equal(got, want) { t.Errorf("got initial state %q, want %q", got, want) } - } diff --git a/grpcreplay/text_format.go b/grpcreplay/text_format.go index 08da353..8192c78 100644 --- a/grpcreplay/text_format.go +++ b/grpcreplay/text_format.go @@ -55,6 +55,7 @@ func (w *textWriter) writeEntry(e *entry) error { if err != nil { return err } + bytes = removeExtraSpaces(bytes) if _, err := fmt.Fprintln(w.w, len(bytes)); err != nil { return err } @@ -62,6 +63,31 @@ func (w *textWriter) writeEntry(e *entry) error { return err } +// Remove extra spaces after a colon in "field: value" lines. +// prototext inserts these to discourage its use as a stable format, +// but the more stability the better to avoid spurious diffs in CLs. +func removeExtraSpaces(bs []byte) []byte { + var buf bytes.Buffer + for len(bs) > 0 { + var line []byte + var nlfound bool + line, bs, nlfound = bytes.Cut(bs, []byte{'\n'}) + field, value, found := bytes.Cut(line, []byte{':'}) + if !found { + buf.Write(line) + } else { + buf.Write(field) + buf.WriteByte(':') + buf.WriteByte(' ') + buf.Write(bytes.TrimSpace(value)) + } + if nlfound { + buf.WriteByte('\n') + } + } + return buf.Bytes() +} + type textReader struct { r *bufio.Reader file string diff --git a/grpcreplay/text_format_test.go b/grpcreplay/text_format_test.go new file mode 100644 index 0000000..96cb40c --- /dev/null +++ b/grpcreplay/text_format_test.go @@ -0,0 +1,54 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package grpcreplay + +import "testing" + +func TestRemoveExtraSpaces(t *testing.T) { + in := ` + fields: { + key: "value" + value: { + array_value: { + values: { + double_value: 0.30135461688041687 + } + values: { + double_value: 0.3094993531703949 + } + } + } + } +` + want := ` + fields: { + key: "value" + value: { + array_value: { + values: { + double_value: 0.30135461688041687 + } + values: { + double_value: 0.3094993531703949 + } + } + } + } +` + got := string(removeExtraSpaces([]byte(in))) + if got != want { + t.Errorf("got\n%s\nwant\n%s", got, want) + } +}