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 33 using System; 34 using System.Text; 35 using NUnit.Framework; 36 using System.IO; 37 #if !NET35 38 using System.Threading.Tasks; 39 #endif 40 41 namespace Google.Protobuf 42 { 43 public class ByteStringTest 44 { 45 [Test] Equality()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] EmptyByteStringHasZeroSize()74 public void EmptyByteStringHasZeroSize() 75 { 76 Assert.AreEqual(0, ByteString.Empty.Length); 77 } 78 79 [Test] CopyFromStringWithExplicitEncoding()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] IsEmptyWhenEmpty()91 public void IsEmptyWhenEmpty() 92 { 93 Assert.IsTrue(ByteString.CopyFromUtf8("").IsEmpty); 94 } 95 96 [Test] IsEmptyWhenNotEmpty()97 public void IsEmptyWhenNotEmpty() 98 { 99 Assert.IsFalse(ByteString.CopyFromUtf8("X").IsEmpty); 100 } 101 102 [Test] CopyFromByteArrayCopiesContents()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] ToByteArrayCopiesContents()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] CopyFromUtf8UsesUtf8()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] CopyFromPortion()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] ToStringUtf8()146 public void ToStringUtf8() 147 { 148 ByteString bs = ByteString.CopyFromUtf8("\u20ac"); 149 Assert.AreEqual("\u20ac", bs.ToStringUtf8()); 150 } 151 152 [Test] ToStringWithExplicitEncoding()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] FromBase64_WithText()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] FromBase64_Empty()169 public void FromBase64_Empty() 170 { 171 // Optimization which also fixes issue 61. 172 Assert.AreSame(ByteString.Empty, ByteString.FromBase64("")); 173 } 174 175 [Test] FromStream_Seekable()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] FromStream_NotSeekable()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] FromStreamAsync_Seekable()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] FromStreamAsync_NotSeekable()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] GetHashCode_Regression()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/protocolbuffers/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 } 237 }