1#region Copyright notice and license
2// Protocol Buffers - Google's data interchange format
3// Copyright 2008 Google Inc.  All rights reserved.
4// https://developers.google.com/protocol-buffers/
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met:
9//
10//     * Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer.
12//     * Redistributions in binary form must reproduce the above
13// copyright notice, this list of conditions and the following disclaimer
14// in the documentation and/or other materials provided with the
15// distribution.
16//     * Neither the name of Google Inc. nor the names of its
17// contributors may be used to endorse or promote products derived from
18// this software without specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31#endregion
32
33using NUnit.Framework;
34using ProtobufUnittest;
35using System;
36using System.IO;
37using UnitTest.Issues.TestProtos;
38
39namespace Google.Protobuf.Test
40{
41    class Proto3OptionalTest
42    {
43        [Test]
44        public void OptionalInt32FieldLifecycle()
45        {
46            var message = new TestProto3Optional();
47            Assert.IsFalse(message.HasOptionalInt32);
48            Assert.AreEqual(0, message.OptionalInt32);
49
50            message.OptionalInt32 = 5;
51            Assert.IsTrue(message.HasOptionalInt32);
52            Assert.AreEqual(5, message.OptionalInt32);
53
54            message.OptionalInt32 = 0;
55            Assert.IsTrue(message.HasOptionalInt32);
56            Assert.AreEqual(0, message.OptionalInt32);
57
58            message.ClearOptionalInt32();
59            Assert.IsFalse(message.HasOptionalInt32);
60            Assert.AreEqual(0, message.OptionalInt32);
61        }
62
63        [Test]
64        public void OptionalStringFieldLifecycle()
65        {
66            var message = new TestProto3Optional();
67            Assert.IsFalse(message.HasOptionalString);
68            Assert.AreEqual("", message.OptionalString);
69
70            message.OptionalString = "x";
71            Assert.IsTrue(message.HasOptionalString);
72            Assert.AreEqual("x", message.OptionalString);
73
74            message.OptionalString = "";
75            Assert.IsTrue(message.HasOptionalString);
76            Assert.AreEqual("", message.OptionalString);
77
78            message.ClearOptionalString();
79            Assert.IsFalse(message.HasOptionalString);
80            Assert.AreEqual("", message.OptionalString);
81
82            Assert.Throws<ArgumentNullException>(() => message.OptionalString = null);
83        }
84
85        [Test]
86        public void Clone()
87        {
88            var original = new TestProto3Optional { OptionalInt64 = 0L };
89
90            var clone = original.Clone();
91            Assert.False(clone.HasOptionalInt32);
92            Assert.AreEqual(0, clone.OptionalInt32);
93            Assert.True(clone.HasOptionalInt64);
94            Assert.AreEqual(0L, clone.OptionalInt64);
95        }
96
97        [Test]
98        public void Serialization_NotSet()
99        {
100            var stream = new MemoryStream();
101            var message = new TestProto3Optional();
102            message.WriteTo(stream);
103            Assert.AreEqual(0, stream.Length);
104        }
105
106        [Test]
107        public void Serialization_SetToDefault()
108        {
109            var stream = new MemoryStream();
110            var message = new TestProto3Optional { OptionalInt32 = 0 };
111            message.WriteTo(stream);
112            Assert.AreEqual(2, stream.Length); // Tag and value
113        }
114
115        [Test]
116        public void Serialization_Roundtrip()
117        {
118            var original = new TestProto3Optional { OptionalInt64 = 0L, OptionalFixed32 = 5U };
119            var stream = new MemoryStream();
120            original.WriteTo(stream);
121            stream.Position = 0;
122            var deserialized = TestProto3Optional.Parser.ParseFrom(stream);
123
124            Assert.AreEqual(0, deserialized.OptionalInt32);
125            Assert.IsFalse(deserialized.HasOptionalInt32);
126
127            Assert.AreEqual(0L, deserialized.OptionalInt64);
128            Assert.IsTrue(deserialized.HasOptionalInt64);
129
130            Assert.AreEqual(5U, deserialized.OptionalFixed32);
131            Assert.IsTrue(deserialized.HasOptionalFixed32);
132        }
133
134        [Test]
135        public void Equality_IgnoresPresence()
136        {
137            var message1 = new TestProto3Optional { OptionalInt32 = 0 };
138            var message2 = new TestProto3Optional();
139
140            Assert.IsTrue(message1.Equals(message2));
141            message1.ClearOptionalInt32();
142        }
143
144        [Test]
145        public void MixedFields()
146        {
147            var descriptor = MixedRegularAndOptional.Descriptor;
148            Assert.AreEqual(1, descriptor.Oneofs.Count);
149            Assert.AreEqual(0, descriptor.RealOneofCount);
150            Assert.True(descriptor.Oneofs[0].IsSynthetic);
151        }
152    }
153}
154