PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/MongoDB.Bson.Tests/IO/BsonBinaryReaderTests.cs

http://github.com/mongodb/mongo-csharp-driver
C# | 372 lines | 318 code | 37 blank | 17 comment | 19 complexity | fa1318f3d8e2082b5edba68ed68a7531 MD5 | raw file
Possible License(s): Apache-2.0
  1. /* Copyright 2010-present MongoDB Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. using System;
  16. using System.Collections.Generic;
  17. using System.IO;
  18. using System.Linq;
  19. using FluentAssertions;
  20. using MongoDB.Bson.IO;
  21. using MongoDB.Bson.Serialization;
  22. using MongoDB.Bson.TestHelpers;
  23. using MongoDB.Bson.TestHelpers.XunitExtensions;
  24. using Xunit;
  25. namespace MongoDB.Bson.Tests.IO
  26. {
  27. public class BsonBinaryReaderTests
  28. {
  29. [SkippableFact]
  30. public void BsonBinaryReader_should_support_reading_more_than_2GB()
  31. {
  32. RequireEnvironment.Check().EnvironmentVariable("EXPLICIT");
  33. var binaryData = new BsonBinaryData(new byte[1024 * 1024]);
  34. var tempFileName = Path.GetTempFileName();
  35. try
  36. {
  37. using (var stream = new FileStream(tempFileName, FileMode.Open))
  38. {
  39. using (var binaryWriter = new BsonBinaryWriter(stream))
  40. {
  41. while (stream.Position < (long)int.MaxValue * 4)
  42. {
  43. binaryWriter.WriteStartDocument();
  44. binaryWriter.WriteName("x");
  45. binaryWriter.WriteBinaryData(binaryData);
  46. binaryWriter.WriteEndDocument();
  47. }
  48. }
  49. var endOfFilePosition = stream.Position;
  50. stream.Position = 0;
  51. using (var binaryReader = new BsonBinaryReader(stream))
  52. {
  53. while (!binaryReader.IsAtEndOfFile())
  54. {
  55. binaryReader.ReadStartDocument();
  56. var bookmark = binaryReader.GetBookmark();
  57. binaryReader.ReadName("x");
  58. binaryReader.ReturnToBookmark(bookmark);
  59. binaryReader.ReadName("x");
  60. var readBinaryData = binaryReader.ReadBinaryData();
  61. Assert.Equal(binaryData.Bytes.Length, readBinaryData.Bytes.Length);
  62. binaryReader.ReadEndDocument();
  63. }
  64. }
  65. Assert.Equal(endOfFilePosition, stream.Position);
  66. }
  67. }
  68. finally
  69. {
  70. try
  71. {
  72. File.Delete(tempFileName);
  73. }
  74. catch
  75. {
  76. // ignore exceptions
  77. }
  78. }
  79. }
  80. [Theory]
  81. [ParameterAttributeData]
  82. public void BsonBinaryReader_should_support_reading_multiple_documents(
  83. [Range(0, 3)]
  84. int numberOfDocuments)
  85. {
  86. var document = new BsonDocument("x", 1);
  87. var bson = document.ToBson();
  88. var input = Enumerable.Repeat(bson, numberOfDocuments).Aggregate(Enumerable.Empty<byte>(), (a, b) => a.Concat(b)).ToArray();
  89. var expectedResult = Enumerable.Repeat(document, numberOfDocuments);
  90. using (var stream = new MemoryStream(input))
  91. using (var binaryReader = new BsonBinaryReader(stream))
  92. {
  93. var result = new List<BsonDocument>();
  94. while (!binaryReader.IsAtEndOfFile())
  95. {
  96. binaryReader.ReadStartDocument();
  97. var name = binaryReader.ReadName();
  98. var value = binaryReader.ReadInt32();
  99. binaryReader.ReadEndDocument();
  100. var resultDocument = new BsonDocument(name, value);
  101. result.Add(resultDocument);
  102. }
  103. result.Should().Equal(expectedResult);
  104. }
  105. }
  106. [Theory]
  107. [InlineData("00000000 f0 6100", "a")]
  108. [InlineData("00000000 08 6100 00 f0 6200", "b")]
  109. [InlineData("00000000 03 6100 00000000 f0 6200", "a.b")]
  110. [InlineData("00000000 03 6100 00000000 08 6200 00 f0 6300", "a.c")]
  111. [InlineData("00000000 04 6100 00000000 f0", "a.0")]
  112. [InlineData("00000000 04 6100 00000000 08 3000 00 f0", "a.1")]
  113. [InlineData("00000000 04 6100 00000000 03 3000 00000000 f0 6200", "a.0.b")]
  114. [InlineData("00000000 04 6100 00000000 03 3000 00000000 08 6200 00 f0 6300", "a.0.c")]
  115. [InlineData("00000000 04 6100 00000000 08 3000 00 03 3100 00000000 f0 6200", "a.1.b")]
  116. [InlineData("00000000 04 6100 00000000 08 3000 00 03 3200 00000000 08 6200 00 f0 6300", "a.1.c")]
  117. public void ReadBsonType_should_throw_when_bson_type_is_invalid(string hexBytes, string expectedElementName)
  118. {
  119. var bytes = BsonUtils.ParseHexString(hexBytes.Replace(" ", ""));
  120. var expectedMessage = $"Detected unknown BSON type \"\\xf0\" for fieldname \"{expectedElementName}\". Are you using the latest driver version?";
  121. using (var memoryStream = new MemoryStream(bytes))
  122. using (var subject = new BsonBinaryReader(memoryStream))
  123. {
  124. Action action = () => BsonSerializer.Deserialize<BsonDocument>(subject);
  125. action.ShouldThrow<FormatException>().WithMessage(expectedMessage);
  126. }
  127. }
  128. [Fact]
  129. public void TestHelloWorld()
  130. {
  131. string byteString = @"\x16\x00\x00\x00\x02hello\x00\x06\x00\x00\x00world\x00\x00";
  132. byte[] bytes = DecodeByteString(byteString);
  133. var stream = new MemoryStream(bytes);
  134. using (var bsonReader = new BsonBinaryReader(stream))
  135. {
  136. bsonReader.ReadStartDocument();
  137. Assert.Equal(BsonType.String, bsonReader.ReadBsonType());
  138. Assert.Equal("hello", bsonReader.ReadName());
  139. Assert.Equal("world", bsonReader.ReadString());
  140. bsonReader.ReadEndDocument();
  141. }
  142. }
  143. [Fact]
  144. public void TestBsonAwesome()
  145. {
  146. string byteString = @"1\x00\x00\x00\x04BSON\x00&\x00\x00\x00\x020\x00\x08\x00\x00\x00awesome\x00\x011\x00333333\x14@\x102\x00\xc2\x07\x00\x00\x00\x00";
  147. byte[] bytes = DecodeByteString(byteString);
  148. var stream = new MemoryStream(bytes);
  149. using (var bsonReader = new BsonBinaryReader(stream))
  150. {
  151. bsonReader.ReadStartDocument();
  152. Assert.Equal(BsonType.Array, bsonReader.ReadBsonType());
  153. Assert.Equal("BSON", bsonReader.ReadName());
  154. bsonReader.ReadStartArray();
  155. Assert.Equal(BsonType.String, bsonReader.ReadBsonType());
  156. Assert.Equal("awesome", bsonReader.ReadString());
  157. Assert.Equal(BsonType.Double, bsonReader.ReadBsonType());
  158. Assert.Equal(5.05, bsonReader.ReadDouble());
  159. Assert.Equal(BsonType.Int32, bsonReader.ReadBsonType());
  160. Assert.Equal(1986, bsonReader.ReadInt32());
  161. bsonReader.ReadEndArray();
  162. bsonReader.ReadEndDocument();
  163. }
  164. }
  165. [Fact]
  166. public void TestIsAtEndOfFileWithTwoDocuments()
  167. {
  168. var expected = new BsonDocument("x", 1);
  169. byte[] bson;
  170. using (var stream = new MemoryStream())
  171. using (var writer = new BsonBinaryWriter(stream))
  172. {
  173. BsonSerializer.Serialize(writer, expected);
  174. BsonSerializer.Serialize(writer, expected);
  175. bson = stream.ToArray();
  176. }
  177. using (var stream = new MemoryStream(bson))
  178. using (var reader = new BsonBinaryReader(stream))
  179. {
  180. var count = 0;
  181. while (!reader.IsAtEndOfFile())
  182. {
  183. var document = BsonSerializer.Deserialize<BsonDocument>(reader);
  184. Assert.Equal(expected, document);
  185. count++;
  186. }
  187. Assert.Equal(2, count);
  188. }
  189. }
  190. [Fact]
  191. public void TestReadRawBsonArray()
  192. {
  193. var bsonDocument = new BsonDocument { { "_id", 1 }, { "A", new BsonArray { 1, 2 } } };
  194. var bson = bsonDocument.ToBson();
  195. using (var document = BsonSerializer.Deserialize<CWithRawBsonArray>(bson))
  196. {
  197. Assert.Equal(1, document.Id);
  198. Assert.Equal(2, document.A.Count);
  199. Assert.Equal(1, document.A[0].AsInt32);
  200. Assert.Equal(2, document.A[1].AsInt32);
  201. Assert.True(bson.SequenceEqual(document.ToBson()));
  202. }
  203. }
  204. [Fact]
  205. public void TestReadRawBsonDocument()
  206. {
  207. var document = new BsonDocument { { "x", 1 }, { "y", 2 } };
  208. var bson = document.ToBson();
  209. using (var rawDocument = BsonSerializer.Deserialize<RawBsonDocument>(bson))
  210. {
  211. Assert.Equal(1, rawDocument["x"].ToInt32());
  212. Assert.Equal(2, rawDocument["y"].ToInt32());
  213. Assert.True(bson.SequenceEqual(rawDocument.ToBson()));
  214. }
  215. }
  216. [Theory]
  217. [ParameterAttributeData]
  218. [ResetGuidModeAfterTest]
  219. public void ReadBinaryData_subtype_3_should_use_GuidRepresentation_from_settings(
  220. [ClassValues(typeof(GuidModeValues))] GuidMode mode,
  221. [Values(
  222. GuidRepresentation.CSharpLegacy,
  223. GuidRepresentation.JavaLegacy,
  224. GuidRepresentation.PythonLegacy,
  225. GuidRepresentation.Unspecified)] GuidRepresentation guidRepresentation)
  226. {
  227. mode.Set();
  228. #pragma warning disable 618
  229. var settings = new BsonBinaryReaderSettings();
  230. if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2)
  231. {
  232. settings.GuidRepresentation = guidRepresentation;
  233. }
  234. var bytes = new byte[] { 29, 0, 0, 0, 5, 120, 0, 16, 0, 0, 0, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 };
  235. using (var stream = new MemoryStream(bytes))
  236. using (var reader = new BsonBinaryReader(stream, settings))
  237. {
  238. reader.ReadStartDocument();
  239. var type = reader.ReadBsonType();
  240. var name = reader.ReadName();
  241. var binaryData = reader.ReadBinaryData();
  242. var endOfDocument = reader.ReadBsonType();
  243. reader.ReadEndDocument();
  244. name.Should().Be("x");
  245. type.Should().Be(BsonType.Binary);
  246. binaryData.SubType.Should().Be(BsonBinarySubType.UuidLegacy);
  247. binaryData.Bytes.Should().Equal(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });
  248. if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2)
  249. {
  250. binaryData.GuidRepresentation.Should().Be(guidRepresentation);
  251. }
  252. endOfDocument.Should().Be(BsonType.EndOfDocument);
  253. stream.Position.Should().Be(stream.Length);
  254. }
  255. #pragma warning restore 618
  256. }
  257. [Theory]
  258. [ParameterAttributeData]
  259. [ResetGuidModeAfterTest]
  260. public void ReadBinaryData_subtype_4_should_use_GuidRepresentation_Standard(
  261. [ClassValues(typeof(GuidModeValues))] GuidMode mode,
  262. [Values(
  263. GuidRepresentation.CSharpLegacy,
  264. GuidRepresentation.JavaLegacy,
  265. GuidRepresentation.PythonLegacy,
  266. GuidRepresentation.Standard,
  267. GuidRepresentation.Unspecified)] GuidRepresentation guidRepresentation)
  268. {
  269. mode.Set();
  270. #pragma warning disable 618
  271. var settings = new BsonBinaryReaderSettings();
  272. if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2)
  273. {
  274. settings.GuidRepresentation = guidRepresentation;
  275. }
  276. var bytes = new byte[] { 29, 0, 0, 0, 5, 120, 0, 16, 0, 0, 0, 4, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 };
  277. using (var stream = new MemoryStream(bytes))
  278. using (var reader = new BsonBinaryReader(stream, settings))
  279. {
  280. reader.ReadStartDocument();
  281. var type = reader.ReadBsonType();
  282. var name = reader.ReadName();
  283. var binaryData = reader.ReadBinaryData();
  284. var endOfDocument = reader.ReadBsonType();
  285. reader.ReadEndDocument();
  286. name.Should().Be("x");
  287. type.Should().Be(BsonType.Binary);
  288. binaryData.SubType.Should().Be(BsonBinarySubType.UuidStandard);
  289. binaryData.Bytes.Should().Equal(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });
  290. if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2)
  291. {
  292. binaryData.GuidRepresentation.Should().Be(GuidRepresentation.Standard);
  293. }
  294. endOfDocument.Should().Be(BsonType.EndOfDocument);
  295. stream.Position.Should().Be(stream.Length);
  296. }
  297. #pragma warning restore 618
  298. }
  299. // private methods
  300. private static string __hexDigits = "0123456789abcdef";
  301. private byte[] DecodeByteString(string byteString)
  302. {
  303. List<byte> bytes = new List<byte>(byteString.Length);
  304. for (int i = 0; i < byteString.Length;)
  305. {
  306. char c = byteString[i++];
  307. if (c == '\\' && ((c = byteString[i++]) != '\\'))
  308. {
  309. int x = __hexDigits.IndexOf(char.ToLower(byteString[i++]));
  310. int y = __hexDigits.IndexOf(char.ToLower(byteString[i++]));
  311. bytes.Add((byte)(16 * x + y));
  312. }
  313. else
  314. {
  315. bytes.Add((byte)c);
  316. }
  317. }
  318. return bytes.ToArray();
  319. }
  320. // nested classes
  321. private class CWithRawBsonArray : IDisposable
  322. {
  323. public int Id { get; set; }
  324. public RawBsonArray A { get; set; }
  325. public void Dispose()
  326. {
  327. if (A != null)
  328. {
  329. A.Dispose();
  330. A = null;
  331. }
  332. }
  333. }
  334. }
  335. }