blob: da467ce519640a63d172172a5e63a509bb29660a [file] [log] [blame]
Googler87dd1802017-12-20 04:34:12 +01001#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 System;
34using System.Text;
35using NUnit.Framework;
36using System.IO;
37#if !NET35
38using System.Threading.Tasks;
39#endif
40
41namespace Google.Protobuf
42{
43 public class ByteStringTest
44 {
45 [Test]
46 public void Equality()
47 {
48 ByteString b1 = ByteString.CopyFrom(1, 2, 3);
49 ByteString b2 = ByteString.CopyFrom(1, 2, 3);
50 ByteString b3 = ByteString.CopyFrom(1, 2, 4);
51 ByteString b4 = ByteString.CopyFrom(1, 2, 3, 4);
52 EqualityTester.AssertEquality(b1, b1);
53 EqualityTester.AssertEquality(b1, b2);
54 EqualityTester.AssertInequality(b1, b3);
55 EqualityTester.AssertInequality(b1, b4);
56 EqualityTester.AssertInequality(b1, null);
57#pragma warning disable 1718 // Deliberately calling ==(b1, b1) and !=(b1, b1)
58 Assert.IsTrue(b1 == b1);
59 Assert.IsTrue(b1 == b2);
60 Assert.IsFalse(b1 == b3);
61 Assert.IsFalse(b1 == b4);
62 Assert.IsFalse(b1 == null);
63 Assert.IsTrue((ByteString) null == null);
64 Assert.IsFalse(b1 != b1);
65 Assert.IsFalse(b1 != b2);
66#pragma warning disable 1718
67 Assert.IsTrue(b1 != b3);
68 Assert.IsTrue(b1 != b4);
69 Assert.IsTrue(b1 != null);
70 Assert.IsFalse((ByteString) null != null);
71 }
72
73 [Test]
74 public void EmptyByteStringHasZeroSize()
75 {
76 Assert.AreEqual(0, ByteString.Empty.Length);
77 }
78
79 [Test]
80 public void CopyFromStringWithExplicitEncoding()
81 {
82 ByteString bs = ByteString.CopyFrom("AB", Encoding.Unicode);
83 Assert.AreEqual(4, bs.Length);
84 Assert.AreEqual(65, bs[0]);
85 Assert.AreEqual(0, bs[1]);
86 Assert.AreEqual(66, bs[2]);
87 Assert.AreEqual(0, bs[3]);
88 }
89
90 [Test]
91 public void IsEmptyWhenEmpty()
92 {
93 Assert.IsTrue(ByteString.CopyFromUtf8("").IsEmpty);
94 }
95
96 [Test]
97 public void IsEmptyWhenNotEmpty()
98 {
99 Assert.IsFalse(ByteString.CopyFromUtf8("X").IsEmpty);
100 }
101
102 [Test]
103 public void CopyFromByteArrayCopiesContents()
104 {
105 byte[] data = new byte[1];
106 data[0] = 10;
107 ByteString bs = ByteString.CopyFrom(data);
108 Assert.AreEqual(10, bs[0]);
109 data[0] = 5;
110 Assert.AreEqual(10, bs[0]);
111 }
112
113 [Test]
114 public void ToByteArrayCopiesContents()
115 {
116 ByteString bs = ByteString.CopyFromUtf8("Hello");
117 byte[] data = bs.ToByteArray();
118 Assert.AreEqual((byte)'H', data[0]);
119 Assert.AreEqual((byte)'H', bs[0]);
120 data[0] = 0;
121 Assert.AreEqual(0, data[0]);
122 Assert.AreEqual((byte)'H', bs[0]);
123 }
124
125 [Test]
126 public void CopyFromUtf8UsesUtf8()
127 {
128 ByteString bs = ByteString.CopyFromUtf8("\u20ac");
129 Assert.AreEqual(3, bs.Length);
130 Assert.AreEqual(0xe2, bs[0]);
131 Assert.AreEqual(0x82, bs[1]);
132 Assert.AreEqual(0xac, bs[2]);
133 }
134
135 [Test]
136 public void CopyFromPortion()
137 {
138 byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6};
139 ByteString bs = ByteString.CopyFrom(data, 2, 3);
140 Assert.AreEqual(3, bs.Length);
141 Assert.AreEqual(2, bs[0]);
142 Assert.AreEqual(3, bs[1]);
143 }
144
145 [Test]
146 public void ToStringUtf8()
147 {
148 ByteString bs = ByteString.CopyFromUtf8("\u20ac");
149 Assert.AreEqual("\u20ac", bs.ToStringUtf8());
150 }
151
152 [Test]
153 public void ToStringWithExplicitEncoding()
154 {
155 ByteString bs = ByteString.CopyFrom("\u20ac", Encoding.Unicode);
156 Assert.AreEqual("\u20ac", bs.ToString(Encoding.Unicode));
157 }
158
159 [Test]
160 public void FromBase64_WithText()
161 {
162 byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6};
163 string base64 = Convert.ToBase64String(data);
164 ByteString bs = ByteString.FromBase64(base64);
165 Assert.AreEqual(data, bs.ToByteArray());
166 }
167
168 [Test]
169 public void FromBase64_Empty()
170 {
171 // Optimization which also fixes issue 61.
172 Assert.AreSame(ByteString.Empty, ByteString.FromBase64(""));
173 }
174
175 [Test]
176 public void FromStream_Seekable()
177 {
178 var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
179 // Consume the first byte, just to test that it's "from current position"
180 stream.ReadByte();
181 var actual = ByteString.FromStream(stream);
182 ByteString expected = ByteString.CopyFrom(2, 3, 4, 5);
183 Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
184 }
185
186 [Test]
187 public void FromStream_NotSeekable()
188 {
189 var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
190 // Consume the first byte, just to test that it's "from current position"
191 stream.ReadByte();
192 // Wrap the original stream in LimitedInputStream, which has CanSeek=false
193 var limitedStream = new LimitedInputStream(stream, 3);
194 var actual = ByteString.FromStream(limitedStream);
195 ByteString expected = ByteString.CopyFrom(2, 3, 4);
196 Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
197 }
198
199#if !NET35
200 [Test]
201 public async Task FromStreamAsync_Seekable()
202 {
203 var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
204 // Consume the first byte, just to test that it's "from current position"
205 stream.ReadByte();
206 var actual = await ByteString.FromStreamAsync(stream);
207 ByteString expected = ByteString.CopyFrom(2, 3, 4, 5);
208 Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
209 }
210
211 [Test]
212 public async Task FromStreamAsync_NotSeekable()
213 {
214 var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
215 // Consume the first byte, just to test that it's "from current position"
216 stream.ReadByte();
217 // Wrap the original stream in LimitedInputStream, which has CanSeek=false
218 var limitedStream = new LimitedInputStream(stream, 3);
219 var actual = await ByteString.FromStreamAsync(limitedStream);
220 ByteString expected = ByteString.CopyFrom(2, 3, 4);
221 Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
222 }
223#endif
224
225 [Test]
226 public void GetHashCode_Regression()
227 {
228 // We used to have an awful hash algorithm where only the last four
229 // bytes were relevant. This is a regression test for
230 // https://github.com/google/protobuf/issues/2511
231
232 ByteString b1 = ByteString.CopyFrom(100, 1, 2, 3, 4);
233 ByteString b2 = ByteString.CopyFrom(200, 1, 2, 3, 4);
234 Assert.AreNotEqual(b1.GetHashCode(), b2.GetHashCode());
235 }
236 }
Jakob Buchgraber2b49f672017-04-26 15:37:42 +0200237}