1ffe3c632Sopenharmony_ci#region Copyright notice and license 2ffe3c632Sopenharmony_ci// Protocol Buffers - Google's data interchange format 3ffe3c632Sopenharmony_ci// Copyright 2015 Google Inc. All rights reserved. 4ffe3c632Sopenharmony_ci// https://developers.google.com/protocol-buffers/ 5ffe3c632Sopenharmony_ci// 6ffe3c632Sopenharmony_ci// Redistribution and use in source and binary forms, with or without 7ffe3c632Sopenharmony_ci// modification, are permitted provided that the following conditions are 8ffe3c632Sopenharmony_ci// met: 9ffe3c632Sopenharmony_ci// 10ffe3c632Sopenharmony_ci// * Redistributions of source code must retain the above copyright 11ffe3c632Sopenharmony_ci// notice, this list of conditions and the following disclaimer. 12ffe3c632Sopenharmony_ci// * Redistributions in binary form must reproduce the above 13ffe3c632Sopenharmony_ci// copyright notice, this list of conditions and the following disclaimer 14ffe3c632Sopenharmony_ci// in the documentation and/or other materials provided with the 15ffe3c632Sopenharmony_ci// distribution. 16ffe3c632Sopenharmony_ci// * Neither the name of Google Inc. nor the names of its 17ffe3c632Sopenharmony_ci// contributors may be used to endorse or promote products derived from 18ffe3c632Sopenharmony_ci// this software without specific prior written permission. 19ffe3c632Sopenharmony_ci// 20ffe3c632Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21ffe3c632Sopenharmony_ci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22ffe3c632Sopenharmony_ci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23ffe3c632Sopenharmony_ci// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24ffe3c632Sopenharmony_ci// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25ffe3c632Sopenharmony_ci// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26ffe3c632Sopenharmony_ci// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27ffe3c632Sopenharmony_ci// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28ffe3c632Sopenharmony_ci// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29ffe3c632Sopenharmony_ci// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30ffe3c632Sopenharmony_ci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31ffe3c632Sopenharmony_ci#endregion 32ffe3c632Sopenharmony_ci 33ffe3c632Sopenharmony_ciusing NUnit.Framework; 34ffe3c632Sopenharmony_ciusing System; 35ffe3c632Sopenharmony_ciusing System.Buffers; 36ffe3c632Sopenharmony_ciusing Google.Protobuf.Buffers; 37ffe3c632Sopenharmony_ci 38ffe3c632Sopenharmony_cinamespace Google.Protobuf 39ffe3c632Sopenharmony_ci{ 40ffe3c632Sopenharmony_ci public static class MessageParsingHelpers 41ffe3c632Sopenharmony_ci { 42ffe3c632Sopenharmony_ci public static void AssertReadingMessage<T>(MessageParser<T> parser, byte[] bytes, Action<T> assert) where T : IMessage<T> 43ffe3c632Sopenharmony_ci { 44ffe3c632Sopenharmony_ci var parsedStream = parser.ParseFrom(bytes); 45ffe3c632Sopenharmony_ci 46ffe3c632Sopenharmony_ci // Load content as single segment 47ffe3c632Sopenharmony_ci var parsedBuffer = parser.ParseFrom(new ReadOnlySequence<byte>(bytes)); 48ffe3c632Sopenharmony_ci assert(parsedBuffer); 49ffe3c632Sopenharmony_ci 50ffe3c632Sopenharmony_ci // Load content as multiple segments 51ffe3c632Sopenharmony_ci parsedBuffer = parser.ParseFrom(ReadOnlySequenceFactory.CreateWithContent(bytes)); 52ffe3c632Sopenharmony_ci assert(parsedBuffer); 53ffe3c632Sopenharmony_ci 54ffe3c632Sopenharmony_ci assert(parsedStream); 55ffe3c632Sopenharmony_ci } 56ffe3c632Sopenharmony_ci 57ffe3c632Sopenharmony_ci public static void AssertReadingMessage(MessageParser parser, byte[] bytes, Action<IMessage> assert) 58ffe3c632Sopenharmony_ci { 59ffe3c632Sopenharmony_ci var parsedStream = parser.ParseFrom(bytes); 60ffe3c632Sopenharmony_ci 61ffe3c632Sopenharmony_ci // Load content as single segment 62ffe3c632Sopenharmony_ci var parsedBuffer = parser.ParseFrom(new ReadOnlySequence<byte>(bytes)); 63ffe3c632Sopenharmony_ci assert(parsedBuffer); 64ffe3c632Sopenharmony_ci 65ffe3c632Sopenharmony_ci // Load content as multiple segments 66ffe3c632Sopenharmony_ci parsedBuffer = parser.ParseFrom(ReadOnlySequenceFactory.CreateWithContent(bytes)); 67ffe3c632Sopenharmony_ci assert(parsedBuffer); 68ffe3c632Sopenharmony_ci 69ffe3c632Sopenharmony_ci assert(parsedStream); 70ffe3c632Sopenharmony_ci } 71ffe3c632Sopenharmony_ci 72ffe3c632Sopenharmony_ci public static void AssertReadingMessageThrows<TMessage, TException>(MessageParser<TMessage> parser, byte[] bytes) 73ffe3c632Sopenharmony_ci where TMessage : IMessage<TMessage> 74ffe3c632Sopenharmony_ci where TException : Exception 75ffe3c632Sopenharmony_ci { 76ffe3c632Sopenharmony_ci Assert.Throws<TException>(() => parser.ParseFrom(bytes)); 77ffe3c632Sopenharmony_ci 78ffe3c632Sopenharmony_ci Assert.Throws<TException>(() => parser.ParseFrom(new ReadOnlySequence<byte>(bytes))); 79ffe3c632Sopenharmony_ci } 80ffe3c632Sopenharmony_ci 81ffe3c632Sopenharmony_ci public static void AssertRoundtrip<T>(MessageParser<T> parser, T message, Action<T> additionalAssert = null) where T : IMessage<T> 82ffe3c632Sopenharmony_ci { 83ffe3c632Sopenharmony_ci var bytes = message.ToByteArray(); 84ffe3c632Sopenharmony_ci 85ffe3c632Sopenharmony_ci // also serialize using IBufferWriter and check it leads to the same data 86ffe3c632Sopenharmony_ci var bufferWriter = new ArrayBufferWriter<byte>(); 87ffe3c632Sopenharmony_ci message.WriteTo(bufferWriter); 88ffe3c632Sopenharmony_ci Assert.AreEqual(bytes, bufferWriter.WrittenSpan.ToArray(), "Both serialization approaches need to result in the same data."); 89ffe3c632Sopenharmony_ci 90ffe3c632Sopenharmony_ci // Load content as single segment 91ffe3c632Sopenharmony_ci var parsedBuffer = parser.ParseFrom(new ReadOnlySequence<byte>(bytes)); 92ffe3c632Sopenharmony_ci Assert.AreEqual(message, parsedBuffer); 93ffe3c632Sopenharmony_ci additionalAssert?.Invoke(parsedBuffer); 94ffe3c632Sopenharmony_ci 95ffe3c632Sopenharmony_ci // Load content as multiple segments 96ffe3c632Sopenharmony_ci parsedBuffer = parser.ParseFrom(ReadOnlySequenceFactory.CreateWithContent(bytes)); 97ffe3c632Sopenharmony_ci Assert.AreEqual(message, parsedBuffer); 98ffe3c632Sopenharmony_ci additionalAssert?.Invoke(parsedBuffer); 99ffe3c632Sopenharmony_ci 100ffe3c632Sopenharmony_ci var parsedStream = parser.ParseFrom(bytes); 101ffe3c632Sopenharmony_ci 102ffe3c632Sopenharmony_ci Assert.AreEqual(message, parsedStream); 103ffe3c632Sopenharmony_ci additionalAssert?.Invoke(parsedStream); 104ffe3c632Sopenharmony_ci } 105ffe3c632Sopenharmony_ci 106ffe3c632Sopenharmony_ci public static void AssertWritingMessage(IMessage message) 107ffe3c632Sopenharmony_ci { 108ffe3c632Sopenharmony_ci // serialize using CodedOutputStream 109ffe3c632Sopenharmony_ci var bytes = message.ToByteArray(); 110ffe3c632Sopenharmony_ci 111ffe3c632Sopenharmony_ci int messageSize = message.CalculateSize(); 112ffe3c632Sopenharmony_ci Assert.AreEqual(message.CalculateSize(), bytes.Length); 113ffe3c632Sopenharmony_ci 114ffe3c632Sopenharmony_ci // serialize using IBufferWriter and check it leads to the same output 115ffe3c632Sopenharmony_ci var bufferWriter = new ArrayBufferWriter<byte>(); 116ffe3c632Sopenharmony_ci message.WriteTo(bufferWriter); 117ffe3c632Sopenharmony_ci Assert.AreEqual(bytes, bufferWriter.WrittenSpan.ToArray()); 118ffe3c632Sopenharmony_ci 119ffe3c632Sopenharmony_ci // serialize into a single span and check it leads to the same output 120ffe3c632Sopenharmony_ci var singleSpan = new Span<byte>(new byte[messageSize]); 121ffe3c632Sopenharmony_ci message.WriteTo(singleSpan); 122ffe3c632Sopenharmony_ci Assert.AreEqual(bytes, singleSpan.ToArray()); 123ffe3c632Sopenharmony_ci 124ffe3c632Sopenharmony_ci // test for different IBufferWriter.GetSpan() segment sizes 125ffe3c632Sopenharmony_ci for (int blockSize = 1; blockSize < 256; blockSize *= 2) 126ffe3c632Sopenharmony_ci { 127ffe3c632Sopenharmony_ci var segmentedBufferWriter = new ArrayBufferWriter<byte>(); 128ffe3c632Sopenharmony_ci segmentedBufferWriter.MaxGrowBy = blockSize; 129ffe3c632Sopenharmony_ci message.WriteTo(segmentedBufferWriter); 130ffe3c632Sopenharmony_ci Assert.AreEqual(bytes, segmentedBufferWriter.WrittenSpan.ToArray()); 131ffe3c632Sopenharmony_ci } 132ffe3c632Sopenharmony_ci 133ffe3c632Sopenharmony_ci // if the full message is small enough, try serializing directly into stack-allocated buffer 134ffe3c632Sopenharmony_ci if (bytes.Length <= 256) 135ffe3c632Sopenharmony_ci { 136ffe3c632Sopenharmony_ci Span<byte> stackAllocBuffer = stackalloc byte[bytes.Length]; 137ffe3c632Sopenharmony_ci message.WriteTo(stackAllocBuffer); 138ffe3c632Sopenharmony_ci Assert.AreEqual(bytes, stackAllocBuffer.ToArray()); 139ffe3c632Sopenharmony_ci } 140ffe3c632Sopenharmony_ci } 141ffe3c632Sopenharmony_ci } 142ffe3c632Sopenharmony_ci}