Browse Source

Add test for WriteGetMessage

Bond_009 4 years ago
parent
commit
e1bc322b70

+ 29 - 22
Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs

@@ -288,19 +288,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
         internal static int WriteGetMessage(Span<byte> buffer, int tuner, string name)
         {
             var byteName = string.Format(CultureInfo.InvariantCulture, "/tuner{0}/{1}", tuner, name);
-            int offset = WriteHeaderAndName(buffer, byteName);
-
-            // calculate crc and insert at the end of the message
-            var crc = Crc32.Compute(buffer.Slice(0, offset));
-            BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset), crc);
-
-            return offset + 4;
+            int offset = WriteHeaderAndPayload(buffer, byteName);
+            return FinishPacket(buffer, offset);
         }
 
         private static int WriteSetMessage(Span<byte> buffer, int tuner, string name, string value, uint? lockkey)
         {
             var byteName = string.Format(CultureInfo.InvariantCulture, "/tuner{0}/{1}", tuner, name);
-            int offset = WriteHeaderAndName(buffer, byteName);
+            int offset = WriteHeaderAndPayload(buffer, byteName);
 
             buffer[offset++] = GetSetValue;
             offset += WriteNullTerminatedString(buffer.Slice(offset), value);
@@ -313,17 +308,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
                 offset += 4;
             }
 
-            // calculate crc and insert at the end of the message
-            var crc = Crc32.Compute(buffer.Slice(0, offset));
-            BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset), crc);
-
-            return offset + 4;
+            return FinishPacket(buffer, offset);
         }
 
-        internal static int WriteNullTerminatedString(Span<byte> buffer, ReadOnlySpan<char> value)
+        internal static int WriteNullTerminatedString(Span<byte> buffer, ReadOnlySpan<char> payload)
         {
-            int len = Encoding.UTF8.GetBytes(value, buffer.Slice(1)) + 1;
+            int len = Encoding.UTF8.GetBytes(payload, buffer.Slice(1)) + 1;
 
+            // TODO: variable length: this can be 2 bytes if len > 127
             // Write length in front of value
             buffer[0] = Convert.ToByte(len);
 
@@ -333,21 +325,36 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
             return len;
         }
 
-        private static int WriteHeaderAndName(Span<byte> buffer, ReadOnlySpan<char> payload)
+        private static int WriteHeaderAndPayload(Span<byte> buffer, ReadOnlySpan<char> payload)
         {
-            // insert header bytes into message
+            // Packet type
             BinaryPrimitives.WriteUInt16BigEndian(buffer, GetSetRequest);
-            int offset = 2;
-            // Subtract 4 bytes for header and 4 bytes for crc
-            BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(offset), (ushort)(payload.Length + 2));
 
-            // insert tag name and length
+            // We write the payload length at the end
+            int offset = 4;
+
+            // Tag
             buffer[offset++] = GetSetName;
-            offset += WriteNullTerminatedString(buffer.Slice(offset), payload);
+
+            // Payload length + data
+            int strLen = WriteNullTerminatedString(buffer.Slice(offset), payload);
+            offset += strLen;
 
             return offset;
         }
 
+        private static int FinishPacket(Span<byte> buffer, int offset)
+        {
+            // Payload length
+            BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(2), (ushort)(offset - 4));
+
+            // calculate crc and insert at the end of the message
+            var crc = Crc32.Compute(buffer.Slice(0, offset));
+            BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset), crc);
+
+            return offset + 4;
+        }
+
         private static bool ParseReturnMessage(byte[] buf, int numBytes, out string returnVal)
         {
             returnVal = string.Empty;

+ 19 - 0
tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunManagerTests.cs

@@ -35,5 +35,24 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
             Assert.Equal(expected.Length, len);
             Assert.True(expected.SequenceEqual(buffer.Slice(0, len)));
         }
+
+        [Fact]
+        public void WriteGetMessage_Valid_Success()
+        {
+            ReadOnlySpan<byte> expected = stackalloc byte[]
+            {
+                0, 4,
+                0, 12,
+                3,
+                10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0,
+                0xc0, 0xc9, 0x87, 0x33
+            };
+
+            Span<byte> buffer = stackalloc byte[128];
+            int len = HdHomerunManager.WriteGetMessage(buffer, 0, "N");
+
+            Assert.Equal(expected.Length, len);
+            Assert.True(expected.SequenceEqual(buffer.Slice(0, len)));
+        }
     }
 }