proto: never return nil []byte from Marshal when successful

It is a sufficiently common pattern to do something like the following:
	m.Proto2BytesField, ... = proto.Marshal(m2)

where the user is relying on Marshal to never return a nil byte slice,
otherwise it subtly changes the semantics of how the generated API
handles whether a proto2 "optional bytes" fields is populated or not.

Change-Id: Ie7508dbcdcc5f3295885609a91907c6eb4f04c1e
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/228838
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/proto/encode_test.go b/proto/encode_test.go
index d8aabd9..1cdbabc 100644
--- a/proto/encode_test.go
+++ b/proto/encode_test.go
@@ -247,3 +247,28 @@
 		t.Errorf("after round-trip marshal, got len(m.OptionalBytes) = %v, want %v", got, want)
 	}
 }
+
+// TestEncodeEmpty tests for boundary conditions when producing an empty output.
+// These tests are not necessarily a statement of proper behavior,
+// but exist to detect accidental changes in behavior.
+func TestEncodeEmpty(t *testing.T) {
+	for _, m := range []proto.Message{nil, (*testpb.TestAllTypes)(nil), &testpb.TestAllTypes{}} {
+		isValid := m != nil && m.ProtoReflect().IsValid()
+
+		b, err := proto.Marshal(m)
+		if err != nil {
+			t.Errorf("proto.Marshal() = %v", err)
+		}
+		if isNil := b == nil; isNil == isValid {
+			t.Errorf("proto.Marshal() == nil: %v, want %v", isNil, !isValid)
+		}
+
+		b, err = proto.MarshalOptions{}.Marshal(m)
+		if err != nil {
+			t.Errorf("proto.MarshalOptions{}.Marshal() = %v", err)
+		}
+		if isNil := b == nil; isNil == isValid {
+			t.Errorf("proto.MarshalOptions{}.Marshal() = %v, want %v", isNil, !isValid)
+		}
+	}
+}