", writer);
+ Assert.Contains("<", writer.ToString());
+ }
+
+ [Fact]
+ public void HtmlAttributeEncode_With_TextWriter()
+ {
+ var writer = new StringWriter();
+ HttpUtility.HtmlAttributeEncode("a&b\"c", writer);
+ var result = writer.ToString();
+ Assert.Contains("&", result);
+ Assert.Contains(""", result);
+ }
+
+ [Fact]
+ public void UrlDecode_Byte_Array_Overload()
+ {
+ var bytes = Encoding.UTF8.GetBytes("hello%20world");
+ var result = HttpUtility.UrlDecode(bytes, Encoding.UTF8);
+ Assert.Equal("hello world", result);
+ }
+
+ [Fact]
+ public void UrlDecode_Byte_Array_Null_Returns_Null()
+ {
+ var result = HttpUtility.UrlDecode((byte[])null, Encoding.UTF8);
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void UrlEncode_Byte_Array_Overload()
+ {
+ var bytes = Encoding.UTF8.GetBytes("hello world");
+ var result = HttpUtility.UrlEncode(bytes);
+ Assert.Contains("+", result);
+ }
+
+ [Fact]
+ public void UrlEncode_Byte_Array_Null_Returns_Null()
+ {
+ var result = HttpUtility.UrlEncode((byte[])null);
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void UrlEncode_Byte_Array_With_Offset_Length()
+ {
+ var bytes = Encoding.UTF8.GetBytes("hello world!");
+ var result = HttpUtility.UrlEncode(bytes, 0, bytes.Length);
+ Assert.Contains("+", result);
+ }
+
+ [Fact]
+ public void UrlEncodeToBytes_Byte_Array_Overload()
+ {
+ var bytes = Encoding.UTF8.GetBytes("hello world");
+ var result = HttpUtility.UrlEncodeToBytes(bytes);
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void UrlEncodeToBytes_Byte_Array_Null_Returns_Null()
+ {
+ var result = HttpUtility.UrlEncodeToBytes((byte[])null);
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void UrlEncodeToBytes_With_Encoding()
+ {
+ var result = HttpUtility.UrlEncodeToBytes("hello world", Encoding.UTF8);
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void UrlDecodeToBytes_Byte_Array_Overload()
+ {
+ var bytes = Encoding.UTF8.GetBytes("hello");
+ var result = HttpUtility.UrlDecodeToBytes(bytes);
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void UrlDecodeToBytes_String_With_Encoding()
+ {
+ var result = HttpUtility.UrlDecodeToBytes("hello+world", Encoding.UTF8);
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void UrlDecodeToBytes_Byte_Array_With_Encoded()
+ {
+ var bytes = Encoding.ASCII.GetBytes("hello%20world%26test");
+ var result = HttpUtility.UrlDecodeToBytes(bytes, 0, bytes.Length);
+ var str = Encoding.UTF8.GetString(result);
+ Assert.Equal("hello world&test", str);
+ }
+
+ [Fact]
+ public void ParseQueryString_With_Question_Mark_Prefix()
+ {
+ var result = HttpUtility.ParseQueryString("?key=value");
+ Assert.Equal("value", result["key"]);
+ }
+
+ [Fact]
+ public void ParseQueryString_ToString_Returns_QueryString()
+ {
+ var result = HttpUtility.ParseQueryString("key1=value1&key2=value2");
+ var str = result.ToString();
+ Assert.Contains("key1", str);
+ Assert.Contains("value1", str);
+ }
+
+ [Fact]
+ public void ParseQueryString_With_No_Value()
+ {
+ var result = HttpUtility.ParseQueryString("key&key2=val2");
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void HttpUtility_Constructor()
+ {
+ var util = new HttpUtility();
+ Assert.NotNull(util);
+ }
+
+ [Fact]
+ public void UrlDecode_With_Percent_UTF8_Multi_Byte()
+ {
+ // encode café and decode it back
+ var encoded = HttpUtility.UrlEncode("café", Encoding.UTF8);
+ var decoded = HttpUtility.UrlDecode(encoded, Encoding.UTF8);
+ Assert.Equal("café", decoded);
+ }
+
+ [Fact]
+ public void HtmlDecode_With_Apos_Entity()
+ {
+ var result = HttpUtility.HtmlDecode("hello & world");
+ Assert.Equal("hello & world", result);
+ }
+
+ [Fact]
+ public void HtmlDecode_With_Incomplete_Entity()
+ {
+ var result = HttpUtility.HtmlDecode("a & b");
+ Assert.Contains("&", result);
+ }
+
+ [Fact]
+ public void UrlPathEncode_With_Query()
+ {
+ var result = HttpUtility.UrlPathEncode("path/file name?query=value");
+ Assert.Contains("?query=value", result);
+ Assert.DoesNotContain(" ", result.Substring(0, result.IndexOf('?')));
+ }
+
+ [Fact]
+ public void UrlDecode_Complex_Encoded_Bytes()
+ {
+ var input = Encoding.ASCII.GetBytes("a%20b%2Bc");
+ var result = HttpUtility.UrlDecode(input, 0, input.Length, Encoding.UTF8);
+ Assert.Equal("a b+c", result);
+ }
+
+ [Fact]
+ public void HtmlEncode_Various_Special_Chars()
+ {
+ var result = HttpUtility.HtmlEncode("a
c&d\"e");
+ Assert.Contains("<", result);
+ Assert.Contains(">", result);
+ Assert.Contains("&", result);
+ Assert.Contains(""", result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Numeric_Hex_Large()
+ {
+ var result = HttpUtility.HtmlDecode("☺");
+ Assert.NotNull(result);
+ Assert.True(result.Length >= 1);
+ }
+
+ [Fact]
+ public void UrlEncode_Ascii_Safe_Characters()
+ {
+ var result = HttpUtility.UrlEncode("abc-_.~");
+ // letters, digits, -, _, ., ~ should mostly pass through
+ Assert.Contains("abc", result);
+ }
+
+ [Fact]
+ public void UrlDecodeToBytes_Empty_Returns_Empty()
+ {
+ var result = HttpUtility.UrlDecodeToBytes("");
+ Assert.NotNull(result);
+ Assert.Empty(result);
+ }
+
+ [Fact]
+ public void HtmlEncode_Tab_And_Newlines()
+ {
+ var result = HttpUtility.HtmlEncode("line1\nline2\ttab");
+ Assert.Contains("\n", result);
+ }
+
+ [Fact]
+ public void UrlDecode_Percent_At_End_No_Chars()
+ {
+ var result = HttpUtility.UrlDecode("hello%");
+ Assert.Contains("%", result);
+ }
+
+ [Fact]
+ public void UrlDecode_Incomplete_Percent_Sequence()
+ {
+ var result = HttpUtility.UrlDecode("hello%2");
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void UrlEncode_All_NonAlphanumeric()
+ {
+ var result = HttpUtility.UrlEncode("!@#$%^&*()");
+ Assert.NotEqual("!@#$%^&*()", result);
+ }
+
+ [Fact]
+ public void ParseQueryString_Key_Without_Equals()
+ {
+ var result = HttpUtility.ParseQueryString("lonely");
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void ParseQueryString_Empty_Value()
+ {
+ var result = HttpUtility.ParseQueryString("key=");
+ Assert.Equal("", result["key"]);
+ }
+
+ [Fact]
+ public void UrlDecode_Plus_In_Bytes()
+ {
+ var bytes = Encoding.ASCII.GetBytes("a+b");
+ var result = HttpUtility.UrlDecode(bytes, 0, bytes.Length, Encoding.UTF8);
+ Assert.Equal("a b", result);
+ }
+
+ [Fact]
+ public void UrlDecode_Bytes_Percent_Encoded()
+ {
+ var bytes = Encoding.ASCII.GetBytes("a%41b");
+ var result = HttpUtility.UrlDecode(bytes, 0, bytes.Length, Encoding.UTF8);
+ Assert.Equal("aAb", result);
+ }
+ }
+
+ public class HtmlEncoderTests
+ {
+ [Fact]
+ public void HtmlAttributeEncode_Encodes_Quote_And_Ampersand()
+ {
+ var result = HttpUtility.HtmlAttributeEncode("a\"b&c");
+ Assert.Contains(""", result);
+ Assert.Contains("&", result);
+ }
+
+ [Fact]
+ public void HtmlEncode_Unicode_Char_Above_159()
+ {
+ var result = HttpUtility.HtmlEncode("\u00A0 \u00FF \u2603");
+ Assert.Contains("", result);
+ }
+
+ [Fact]
+ public void HtmlDecode_NumericEntity_Decimal_Large()
+ {
+ var result = HttpUtility.HtmlDecode("☺");
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void HtmlDecode_With_Multiple_Mixed_Entities()
+ {
+ var result = HttpUtility.HtmlDecode("<b>bold</b> & A");
+ Assert.Equal("bold & A", result);
+ }
+ }
+}
diff --git a/RestSharp.Tests.Coverage/HttpUtilityTests.cs b/RestSharp.Tests.Coverage/HttpUtilityTests.cs
new file mode 100644
index 000000000..6b97a5375
--- /dev/null
+++ b/RestSharp.Tests.Coverage/HttpUtilityTests.cs
@@ -0,0 +1,406 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Text;
+using RestSharp.Contrib;
+using Xunit;
+
+namespace RestSharp.Tests.Coverage
+{
+ public class HttpUtilityTests
+ {
+ [Fact]
+ public void UrlEncode_Basic_String()
+ {
+ var result = HttpUtility.UrlEncode("hello world");
+ Assert.Contains("+", result);
+ }
+
+ [Fact]
+ public void UrlEncode_Null_Returns_Null()
+ {
+ var result = HttpUtility.UrlEncode((string)null);
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void UrlEncode_Empty_Returns_Empty()
+ {
+ var result = HttpUtility.UrlEncode("");
+ Assert.Equal("", result);
+ }
+
+ [Fact]
+ public void UrlEncode_Special_Characters()
+ {
+ var result = HttpUtility.UrlEncode("a&b=c?d#e");
+ Assert.DoesNotContain("&", result);
+ Assert.DoesNotContain("=", result);
+ Assert.DoesNotContain("?", result);
+ }
+
+ [Fact]
+ public void UrlEncode_Unicode_Characters()
+ {
+ var result = HttpUtility.UrlEncode("café");
+ Assert.NotEqual("café", result);
+ Assert.Contains("%", result);
+ }
+
+ [Fact]
+ public void UrlDecode_Basic_String()
+ {
+ var result = HttpUtility.UrlDecode("hello+world");
+ Assert.Equal("hello world", result);
+ }
+
+ [Fact]
+ public void UrlDecode_Null_Returns_Null()
+ {
+ var result = HttpUtility.UrlDecode(null);
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void UrlDecode_Percent_Encoded()
+ {
+ var result = HttpUtility.UrlDecode("hello%20world");
+ Assert.Equal("hello world", result);
+ }
+
+ [Fact]
+ public void UrlDecode_With_Encoding()
+ {
+ var result = HttpUtility.UrlDecode("hello+world", Encoding.UTF8);
+ Assert.Equal("hello world", result);
+ }
+
+ [Fact]
+ public void UrlEncode_Bytes()
+ {
+ var bytes = Encoding.UTF8.GetBytes("hello world");
+ var result = HttpUtility.UrlEncode(bytes, 0, bytes.Length);
+ Assert.Contains("+", result);
+ }
+
+ [Fact]
+ public void UrlEncode_With_Encoding()
+ {
+ var result = HttpUtility.UrlEncode("hello world", Encoding.UTF8);
+ Assert.Contains("+", result);
+ }
+
+ [Fact]
+ public void UrlEncodeUnicode_Encodes_Unicode()
+ {
+ var result = HttpUtility.UrlEncodeUnicode("café");
+ Assert.Contains("%", result);
+ }
+
+ [Fact]
+ public void UrlEncodeUnicode_Null_Returns_Null()
+ {
+ var result = HttpUtility.UrlEncodeUnicode(null);
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void UrlDecode_Bytes()
+ {
+ var bytes = Encoding.ASCII.GetBytes("hello+world");
+ var result = HttpUtility.UrlDecode(bytes, 0, bytes.Length, Encoding.UTF8);
+ Assert.Equal("hello world", result);
+ }
+
+ [Fact]
+ public void UrlDecode_Bytes_Null_Returns_Null()
+ {
+ var result = HttpUtility.UrlDecode(null, 0, 0, Encoding.UTF8);
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void UrlDecode_Percent_Hex()
+ {
+ var result = HttpUtility.UrlDecode("%41%42%43");
+ Assert.Equal("ABC", result);
+ }
+
+ [Fact]
+ public void UrlDecode_Unicode_Percent_u()
+ {
+ var result = HttpUtility.UrlDecode("%u0041%u0042%u0043");
+ Assert.Equal("ABC", result);
+ }
+
+ [Fact]
+ public void HtmlEncode_Special_Characters()
+ {
+ var result = HttpUtility.HtmlEncode("");
+ Assert.DoesNotContain("<", result);
+ Assert.DoesNotContain(">", result);
+ Assert.Contains("<", result);
+ Assert.Contains(">", result);
+ }
+
+ [Fact]
+ public void HtmlEncode_Null_Returns_Null()
+ {
+ var result = HttpUtility.HtmlEncode(null);
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void HtmlEncode_Ampersand()
+ {
+ var result = HttpUtility.HtmlEncode("a & b");
+ Assert.Contains("&", result);
+ }
+
+ [Fact]
+ public void HtmlEncode_Quotes()
+ {
+ var result = HttpUtility.HtmlEncode("say \"hello\"");
+ Assert.Contains(""", result);
+ }
+
+ [Fact]
+ public void HtmlEncode_High_Unicode()
+ {
+ var result = HttpUtility.HtmlEncode("hello \u00e9");
+ Assert.Contains("", result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Entities()
+ {
+ var result = HttpUtility.HtmlDecode("<div>test</div>");
+ Assert.Equal("test
", result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Null_Returns_Null()
+ {
+ var result = HttpUtility.HtmlDecode(null);
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Amp()
+ {
+ var result = HttpUtility.HtmlDecode("a & b");
+ Assert.Equal("a & b", result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Numeric_Entity()
+ {
+ var result = HttpUtility.HtmlDecode("ABC");
+ Assert.Equal("ABC", result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Hex_Entity()
+ {
+ var result = HttpUtility.HtmlDecode("ABC");
+ Assert.Equal("ABC", result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Quot()
+ {
+ var result = HttpUtility.HtmlDecode(""hello"");
+ Assert.Equal("\"hello\"", result);
+ }
+
+ [Fact]
+ public void ParseQueryString_Parses_Basic_QueryString()
+ {
+ var result = HttpUtility.ParseQueryString("key1=value1&key2=value2");
+ Assert.Equal("value1", result["key1"]);
+ Assert.Equal("value2", result["key2"]);
+ }
+
+ [Fact]
+ public void ParseQueryString_Empty_String()
+ {
+ var result = HttpUtility.ParseQueryString("");
+ Assert.NotNull(result);
+ Assert.Equal(0, result.Count);
+ }
+
+ [Fact]
+ public void ParseQueryString_Null_Throws()
+ {
+ Assert.Throws(() => HttpUtility.ParseQueryString(null));
+ }
+
+ [Fact]
+ public void ParseQueryString_With_Encoding()
+ {
+ var result = HttpUtility.ParseQueryString("name=test", Encoding.UTF8);
+ Assert.Equal("test", result["name"]);
+ }
+
+ [Fact]
+ public void ParseQueryString_With_Encoded_Values()
+ {
+ var result = HttpUtility.ParseQueryString("name=hello+world&foo=a%26b");
+ Assert.Equal("hello world", result["name"]);
+ Assert.Equal("a&b", result["foo"]);
+ }
+
+ [Fact]
+ public void ParseQueryString_Multiple_Same_Keys()
+ {
+ var result = HttpUtility.ParseQueryString("a=1&a=2");
+ var values = result["a"];
+ Assert.Contains("1", values);
+ Assert.Contains("2", values);
+ }
+
+ [Fact]
+ public void UrlDecode_Roundtrip()
+ {
+ var original = "hello world & goodbye=test?foo#bar";
+ var encoded = HttpUtility.UrlEncode(original);
+ var decoded = HttpUtility.UrlDecode(encoded);
+ Assert.Equal(original, decoded);
+ }
+
+ [Fact]
+ public void HtmlEncodeDecode_Roundtrip()
+ {
+ var original = "Hello & world
";
+ var encoded = HttpUtility.HtmlEncode(original);
+ var decoded = HttpUtility.HtmlDecode(encoded);
+ Assert.Equal(original, decoded);
+ }
+
+ [Fact]
+ public void UrlEncode_Numbers_And_Letters_Unchanged()
+ {
+ var result = HttpUtility.UrlEncode("abc123XYZ");
+ Assert.Equal("abc123XYZ", result);
+ }
+
+ [Fact]
+ public void UrlDecode_Pass_Through_Non_Encoded()
+ {
+ var result = HttpUtility.UrlDecode("simple");
+ Assert.Equal("simple", result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Named_Entity_Apos()
+ {
+ var result = HttpUtility.HtmlDecode("'");
+ // apos is HTML5, might not be supported
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void HtmlDecode_No_Entities_Returns_Same()
+ {
+ var result = HttpUtility.HtmlDecode("plain text");
+ Assert.Equal("plain text", result);
+ }
+
+ [Fact]
+ public void UrlEncode_Bytes_Null_Returns_Null()
+ {
+ var result = HttpUtility.UrlEncode(null, 0, 0);
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void UrlEncode_Bytes_With_Offset()
+ {
+ var bytes = Encoding.UTF8.GetBytes("hello world!");
+ var result = HttpUtility.UrlEncode(bytes, 6, 5);
+ Assert.Contains("world", result);
+ }
+
+ [Fact]
+ public void UrlPathEncode_Encodes_Spaces()
+ {
+ var result = HttpUtility.UrlPathEncode("hello world/path");
+ Assert.DoesNotContain(" ", result);
+ Assert.Contains("/", result);
+ }
+
+ [Fact]
+ public void UrlPathEncode_Null_Returns_Null()
+ {
+ var result = HttpUtility.UrlPathEncode(null);
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void UrlEncodeToBytes_Returns_Encoded_Bytes()
+ {
+ var result = HttpUtility.UrlEncodeToBytes("hello world");
+ Assert.NotNull(result);
+ var str = Encoding.ASCII.GetString(result);
+ Assert.Contains("+", str);
+ }
+
+ [Fact]
+ public void UrlEncodeToBytes_Null_Returns_Null()
+ {
+ var result = HttpUtility.UrlEncodeToBytes((string)null);
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void UrlDecodeToBytes_Decodes_Bytes()
+ {
+ var result = HttpUtility.UrlDecodeToBytes("hello+world");
+ Assert.NotNull(result);
+ var str = Encoding.UTF8.GetString(result);
+ Assert.Equal("hello world", str);
+ }
+
+ [Fact]
+ public void UrlDecodeToBytes_Null_Returns_Null()
+ {
+ var result = HttpUtility.UrlDecodeToBytes((string)null);
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void UrlEncodeUnicodeToBytes_Encodes()
+ {
+ var result = HttpUtility.UrlEncodeUnicodeToBytes("café");
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void UrlDecodeToBytes_Byte_Array()
+ {
+ var input = Encoding.ASCII.GetBytes("hello+world");
+ var result = HttpUtility.UrlDecodeToBytes(input, 0, input.Length);
+ Assert.NotNull(result);
+ var str = Encoding.UTF8.GetString(result);
+ Assert.Equal("hello world", str);
+ }
+
+ [Fact]
+ public void UrlEncodeToBytes_Byte_Array()
+ {
+ var input = Encoding.UTF8.GetBytes("hello world");
+ var result = HttpUtility.UrlEncodeToBytes(input, 0, input.Length);
+ Assert.NotNull(result);
+ var str = Encoding.ASCII.GetString(result);
+ Assert.Contains("+", str);
+ }
+
+ [Fact]
+ public void UrlEncode_Handles_Single_Char_Percent()
+ {
+ var result = HttpUtility.UrlEncode("%");
+ Assert.Equal("%25", result);
+ }
+ }
+}
diff --git a/RestSharp.Tests.Coverage/Last50Tests.cs b/RestSharp.Tests.Coverage/Last50Tests.cs
new file mode 100644
index 000000000..9d98ce59a
--- /dev/null
+++ b/RestSharp.Tests.Coverage/Last50Tests.cs
@@ -0,0 +1,423 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using Newtonsoft.Json.Linq;
+using RestSharp;
+using RestSharp.Contrib;
+using RestSharp.Deserializers;
+using RestSharp.Extensions;
+using Xunit;
+
+namespace RestSharp.Tests.Coverage
+{
+ public class HttpUtilityBytePathTests
+ {
+ [Fact]
+ public void UrlDecode_String_With_Encoding()
+ {
+ var result = HttpUtility.UrlDecode("hello+world", Encoding.UTF8);
+ Assert.Equal("hello world", result);
+ }
+
+ [Fact]
+ public void UrlDecode_String_With_UTF8_MultiByte_Encoding()
+ {
+ // UTF-8 encoded é = %c3%a9
+ var result = HttpUtility.UrlDecode("%c3%a9", Encoding.UTF8);
+ Assert.Equal("\u00e9", result);
+ }
+
+ [Fact]
+ public void UrlDecode_Byte_Array_With_Percent_And_Offset()
+ {
+ var bytes = Encoding.ASCII.GetBytes("a%20b");
+ var result = HttpUtility.UrlDecode(bytes, 0, bytes.Length, Encoding.UTF8);
+ Assert.Equal("a b", result);
+ }
+
+ [Fact]
+ public void UrlDecode_Byte_Array_With_Plus()
+ {
+ var bytes = Encoding.ASCII.GetBytes("hello+world");
+ var result = HttpUtility.UrlDecode(bytes, 0, bytes.Length, Encoding.UTF8);
+ Assert.Equal("hello world", result);
+ }
+
+ [Fact]
+ public void UrlDecode_Byte_Array_With_Hex_Encoded_High()
+ {
+ // %c3%a9 = UTF-8 é
+ var bytes = Encoding.ASCII.GetBytes("%c3%a9");
+ var result = HttpUtility.UrlDecode(bytes, 0, bytes.Length, Encoding.UTF8);
+ Assert.Equal("\u00e9", result);
+ }
+
+ [Fact]
+ public void UrlDecodeToBytes_String_With_Encoding()
+ {
+ var result = HttpUtility.UrlDecodeToBytes("a%20b", Encoding.UTF8);
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void UrlDecodeToBytes_Byte_Array_With_Offset()
+ {
+ var bytes = Encoding.ASCII.GetBytes("a%20b");
+ var result = HttpUtility.UrlDecodeToBytes(bytes, 0, bytes.Length);
+ Assert.NotNull(result);
+ Assert.True(result.Length > 0);
+ }
+
+ [Fact]
+ public void UrlDecodeToBytes_Byte_Array_NoOffset()
+ {
+ var bytes = Encoding.ASCII.GetBytes("a%20b");
+ var result = HttpUtility.UrlDecodeToBytes(bytes);
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void UrlEncode_Byte_Array_NoOffset()
+ {
+ var bytes = Encoding.UTF8.GetBytes("hello");
+ var result = HttpUtility.UrlEncode(bytes);
+ Assert.Equal("hello", result);
+ }
+
+ [Fact]
+ public void UrlEncode_Byte_Array_With_Offset()
+ {
+ var bytes = Encoding.UTF8.GetBytes("hello world");
+ var result = HttpUtility.UrlEncode(bytes, 0, bytes.Length);
+ Assert.Contains("+", result);
+ }
+
+ [Fact]
+ public void UrlEncodeToBytes_String_With_Encoding()
+ {
+ var result = HttpUtility.UrlEncodeToBytes("hello", Encoding.UTF8);
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void UrlEncodeToBytes_Byte_Array_NoOffset()
+ {
+ var bytes = Encoding.UTF8.GetBytes("abc");
+ var result = HttpUtility.UrlEncodeToBytes(bytes);
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void UrlEncodeToBytes_Byte_Array_With_Offset()
+ {
+ var bytes = Encoding.UTF8.GetBytes("abc");
+ var result = HttpUtility.UrlEncodeToBytes(bytes, 0, bytes.Length);
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void UrlEncodeUnicodeToBytes_Returns_Bytes()
+ {
+ var result = HttpUtility.UrlEncodeUnicodeToBytes("test\u4e2d");
+ Assert.NotNull(result);
+ Assert.True(result.Length > 0);
+ }
+
+ [Fact]
+ public void HtmlDecode_To_TextWriter_Null_Source()
+ {
+ var writer = new StringWriter();
+ HttpUtility.HtmlDecode(null, writer);
+ Assert.Equal("", writer.ToString());
+ }
+
+ [Fact]
+ public void HtmlEncode_To_TextWriter_Null_Source()
+ {
+ var writer = new StringWriter();
+ HttpUtility.HtmlEncode(null, writer);
+ Assert.Equal("", writer.ToString());
+ }
+
+ [Fact]
+ public void HtmlAttributeEncode_To_TextWriter_Regular()
+ {
+ var writer = new StringWriter();
+ HttpUtility.HtmlAttributeEncode("test\"value", writer);
+ var result = writer.ToString();
+ Assert.Contains(""", result);
+ }
+
+ [Fact]
+ public void ParseQueryString_With_Encoding_And_QuestionMark()
+ {
+ var result = HttpUtility.ParseQueryString("?a=1&b=2", Encoding.UTF8);
+ Assert.Equal("1", result["a"]);
+ Assert.Equal("2", result["b"]);
+ }
+
+ [Fact]
+ public void HttpQSCollection_ToString_Returns_Formatted()
+ {
+ var coll = HttpUtility.ParseQueryString("a=1&b=2");
+ var str = coll.ToString();
+ Assert.Contains("a=1", str);
+ Assert.Contains("b=2", str);
+ }
+ }
+
+ public class HtmlEncoderInternalPathTests
+ {
+ [Fact]
+ public void HtmlEncode_Empty_String_Returns_Empty()
+ {
+ var result = HttpUtility.HtmlEncode("");
+ Assert.Equal("", result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Empty_Returns_Empty()
+ {
+ var result = HttpUtility.HtmlDecode("");
+ Assert.Equal("", result);
+ }
+
+ [Fact]
+ public void HtmlAttributeEncode_Empty_Returns_Empty()
+ {
+ var result = HttpUtility.HtmlAttributeEncode("");
+ Assert.Equal("", result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Entity_With_Hex_Then_Invalid()
+ {
+ // hex entity with invalid hex digit triggers have_trailing_digits path
+ var result = HttpUtility.HtmlDecode("AG;");
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void UrlPathEncode_SpecialChars()
+ {
+ var result = HttpUtility.UrlPathEncode("/path/to file?q=1");
+ Assert.Contains("%20", result);
+ Assert.Contains("?", result);
+ }
+ }
+
+ public class RestClientDeserializeTests
+ {
+ [Fact]
+ public void Execute_With_Error_Response_Sets_ErrorMessage()
+ {
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactory(new HttpResponse
+ {
+ RawBytes = Encoding.UTF8.GetBytes("error"),
+ ContentType = "text/plain",
+ StatusCode = HttpStatusCode.InternalServerError,
+ ResponseStatus = ResponseStatus.Error,
+ ErrorMessage = "Something failed",
+ ErrorException = new Exception("boom")
+ });
+
+ var response = client.Execute(new RestRequest("api", Method.GET));
+ Assert.Equal(ResponseStatus.Error, response.ResponseStatus);
+ }
+
+ [Fact]
+ public void Execute_Generic_With_Error_Returns_Default_Data()
+ {
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactory(new HttpResponse
+ {
+ RawBytes = Encoding.UTF8.GetBytes(""),
+ ContentType = "application/json",
+ StatusCode = HttpStatusCode.InternalServerError,
+ ResponseStatus = ResponseStatus.Error,
+ ErrorMessage = "Something failed",
+ ErrorException = new Exception("boom")
+ });
+
+ var response = client.Execute(new RestRequest("api", Method.GET));
+ Assert.Equal(ResponseStatus.Error, response.ResponseStatus);
+ }
+
+ [Fact]
+ public void Execute_Generic_Deserialize_With_Handler_Error()
+ {
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactory(new HttpResponse
+ {
+ RawBytes = Encoding.UTF8.GetBytes("not valid json"),
+ ContentType = "application/json",
+ StatusCode = HttpStatusCode.OK,
+ ResponseStatus = ResponseStatus.Completed
+ });
+
+ var response = client.Execute(new RestRequest("api", Method.GET));
+ // Either the data is null due to deserialization error, or an error is caught
+ Assert.NotNull(response);
+ }
+
+ [Fact]
+ public void BuildUri_With_UrlSegment_Substitution()
+ {
+ var client = new RestClient("http://example.com");
+ var request = new RestRequest("api/{id}", Method.GET);
+ request.AddUrlSegment("id", "42");
+ var uri = client.BuildUri(request);
+ Assert.Contains("42", uri.ToString());
+ Assert.DoesNotContain("{id}", uri.ToString());
+ }
+ }
+
+ public class RestRequestFileTests
+ {
+ [Fact]
+ public void AddFile_With_ContentType_Inferred()
+ {
+ var request = new RestRequest();
+ var tmpFile = Path.GetTempFileName();
+ try
+ {
+ File.WriteAllText(tmpFile, "test content");
+ request.AddFile("file", tmpFile);
+ Assert.Single(request.Files);
+ Assert.Equal("file", request.Files[0].Name);
+ }
+ finally
+ {
+ File.Delete(tmpFile);
+ }
+ }
+
+ [Fact]
+ public void AddFile_With_Explicit_ContentType()
+ {
+ var request = new RestRequest();
+ var tmpFile = Path.GetTempFileName();
+ try
+ {
+ File.WriteAllText(tmpFile, "test content");
+ request.AddFile("file", Encoding.UTF8.GetBytes("test content"), "test.txt", "text/plain");
+ Assert.Single(request.Files);
+ }
+ finally
+ {
+ File.Delete(tmpFile);
+ }
+ }
+
+ [Fact]
+ public void UserState_Property()
+ {
+ var request = new RestRequest();
+ Assert.Null(request.UserState);
+ }
+ }
+
+ public class MiscCopyToTests
+ {
+ [Fact]
+ public void CopyTo_Stream_Extension_Works()
+ {
+ var src = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
+ var dst = new MemoryStream();
+ MiscExtensions.CopyTo(src, dst);
+ Assert.Equal(5, dst.Length);
+ }
+ }
+
+ public class JTokenAsStringTests
+ {
+ [Fact]
+ public void AsString_With_Culture()
+ {
+ var token = JToken.Parse("3.14");
+ var result = token.AsString(CultureInfo.InvariantCulture);
+ Assert.Equal("3.14", result);
+ }
+ }
+
+ public class XmlAttributeDeserializerMapTests
+ {
+ [Fact]
+ public void Can_Deserialize_With_Underscore_Names()
+ {
+ var deserializer = new XmlAttributeDeserializer();
+ var response = new RestResponse
+ {
+ Content = "JohnDoe"
+ };
+ var result = deserializer.Deserialize(response);
+ // XmlAttributeDeserializer might not do underscore-to-camelCase mapping
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void Can_Deserialize_With_Dashed_Names()
+ {
+ var deserializer = new XmlAttributeDeserializer();
+ var response = new RestResponse
+ {
+ Content = "JohnDoe"
+ };
+ var result = deserializer.Deserialize(response);
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void GetElementByName_With_LowerCase()
+ {
+ var deserializer = new XmlAttributeDeserializer();
+ var response = new RestResponse
+ {
+ Content = "test"
+ };
+ var result = deserializer.Deserialize(response);
+ Assert.Equal("test", result.TheName);
+ }
+
+ [Fact]
+ public void GetAttributeByName_With_LowerCase()
+ {
+ var deserializer = new XmlAttributeDeserializer();
+ var response = new RestResponse
+ {
+ Content = ""
+ };
+ var result = deserializer.Deserialize(response);
+ Assert.Equal("99", result.Id);
+ }
+ }
+
+ // Model classes
+ public class XmlAttrUnderscoreItem
+ {
+ public string FirstName { get; set; }
+ public string LastName { get; set; }
+ }
+
+ public class XmlAttrDashedItem
+ {
+ public string FirstName { get; set; }
+ public string LastName { get; set; }
+ }
+
+ public class XmlAttrMixed
+ {
+ public string TheName { get; set; }
+ }
+
+ public class XmlAttrById
+ {
+ public string Id { get; set; }
+ }
+}
diff --git a/RestSharp.Tests.Coverage/PushTo80Tests.cs b/RestSharp.Tests.Coverage/PushTo80Tests.cs
new file mode 100644
index 000000000..63170bec5
--- /dev/null
+++ b/RestSharp.Tests.Coverage/PushTo80Tests.cs
@@ -0,0 +1,441 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using RestSharp;
+using RestSharp.Contrib;
+using RestSharp.Deserializers;
+using RestSharp.Extensions;
+using Xunit;
+
+namespace RestSharp.Tests.Coverage
+{
+ public class HtmlEncoderEdgeCaseTests
+ {
+ [Fact]
+ public void HtmlEncode_FullwidthLessThan()
+ {
+ // \uff1c is fullwidth < and \uff1e is fullwidth >
+ var result = HttpUtility.HtmlEncode("\uff1c\uff1e");
+ Assert.Contains("65308", result);
+ Assert.Contains("65310", result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Consecutive_Ampersands()
+ {
+ // Test state transition when & appears inside an entity
+ var result = HttpUtility.HtmlDecode("&<");
+ Assert.Equal("&<", result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Ampersand_Then_Another_Ampersand()
+ {
+ // This should trigger the c == '&' in state != 0 code
+ var result = HttpUtility.HtmlDecode("&invalid&");
+ Assert.Contains("&", result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Hash_Semicolon_Directly()
+ {
+ // should be treated as invalid
+ var result = HttpUtility.HtmlDecode("test");
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Numeric_Entity_With_Trailing_Text()
+ {
+ // Aabc; - digits followed by non-digit in numeric entity
+ var result = HttpUtility.HtmlDecode("Aabc;");
+ Assert.NotNull(result);
+ Assert.True(result.Length > 0);
+ }
+
+ [Fact]
+ public void HtmlDecode_Hex_Entity_Invalid_Chars()
+ {
+ var result = HttpUtility.HtmlDecode("ZZZ;");
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Named_Entity_euro()
+ {
+ var result = HttpUtility.HtmlDecode("€");
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Named_Entity_trade()
+ {
+ var result = HttpUtility.HtmlDecode("™");
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Long_Named_Entity()
+ {
+ var result = HttpUtility.HtmlDecode(" ");
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Entity_At_End_Without_Semicolon()
+ {
+ var result = HttpUtility.HtmlDecode("text&");
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void HtmlDecode_Entity_Number_At_End()
+ {
+ var result = HttpUtility.HtmlDecode("A");
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void UrlEncodeUnicode_HighChar()
+ {
+ // This should trigger the c > 255 path in UrlEncodeChar
+ var result = HttpUtility.UrlEncodeUnicode("\u4e2d"); // Chinese character
+ Assert.Contains("%u", result);
+ }
+
+ [Fact]
+ public void UrlEncodeUnicode_MixedContent()
+ {
+ var result = HttpUtility.UrlEncodeUnicode("hello\u4e16\u754c");
+ Assert.Contains("hello", result);
+ Assert.Contains("%u", result);
+ }
+
+ [Fact]
+ public void UrlPathEncode_Space_Is_Percent20()
+ {
+ // UrlPathEncode should encode space as %20 not +
+ var result = HttpUtility.UrlPathEncode("hello world");
+ Assert.Contains("%20", result);
+ }
+
+ [Fact]
+ public void UrlPathEncode_Control_Char()
+ {
+ var result = HttpUtility.UrlPathEncode("hello\x01world");
+ Assert.Contains("%", result);
+ }
+ }
+
+ public class XmlAttributeDeserializerEdgeTests
+ {
+ [Fact]
+ public void Can_Deserialize_With_RootElement_And_Attributes()
+ {
+ var deserializer = new XmlAttributeDeserializer();
+ deserializer.RootElement = "Data";
+ var response = new RestResponse
+ {
+ Content = "rooted5"
+ };
+ var result = deserializer.Deserialize(response);
+ Assert.Equal("rooted", result.Name);
+ }
+
+ [Fact]
+ public void Can_Deserialize_Attribute_Values()
+ {
+ var deserializer = new XmlAttributeDeserializer();
+ var response = new RestResponse
+ {
+ Content = ""
+ };
+ var result = deserializer.Deserialize(response);
+ Assert.Equal("attr_name", result.Name);
+ Assert.Equal("active", result.Status);
+ }
+
+ [Fact]
+ public void Can_Deserialize_Attribute_CaseInsensitive()
+ {
+ var deserializer = new XmlAttributeDeserializer();
+ var response = new RestResponse
+ {
+ Content = ""
+ };
+ var result = deserializer.Deserialize(response);
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void Can_Deserialize_With_Namespace_And_Attributes()
+ {
+ var deserializer = new XmlAttributeDeserializer();
+ deserializer.Namespace = "http://test.com";
+ var response = new RestResponse
+ {
+ Content = "ns_attr3"
+ };
+ var result = deserializer.Deserialize(response);
+ Assert.Equal("ns_attr", result.Name);
+ }
+
+ [Fact]
+ public void Can_Deserialize_With_DeserializeAs()
+ {
+ var deserializer = new XmlAttributeDeserializer();
+ var response = new RestResponse
+ {
+ Content = "mapped"
+ };
+ var result = deserializer.Deserialize(response);
+ Assert.Equal("mapped", result.TheName);
+ }
+
+ [Fact]
+ public void Can_Deserialize_With_DeserializeAs_Attribute_Flag()
+ {
+ var deserializer = new XmlAttributeDeserializer();
+ var response = new RestResponse
+ {
+ Content = "test"
+ };
+ var result = deserializer.Deserialize(response);
+ Assert.Equal("42", result.Id);
+ Assert.Equal("test", result.Name);
+ }
+
+ [Fact]
+ public void RemoveNamespace_Strips_Namespace()
+ {
+ var deserializer = new XmlAttributeDeserializer();
+ var response = new RestResponse
+ {
+ Content = "stripped"
+ };
+ var result = deserializer.Deserialize(response);
+ Assert.Equal("stripped", result.Name);
+ }
+
+ [Fact]
+ public void Can_Deserialize_List_Of_Nested()
+ {
+ var deserializer = new XmlAttributeDeserializer();
+ var response = new RestResponse
+ {
+ Content = "firstsecond"
+ };
+ var result = deserializer.Deserialize(response);
+ Assert.NotNull(result.Items);
+ Assert.Equal(2, result.Items.Count);
+ Assert.Equal("first", result.Items[0].Text);
+ }
+ }
+
+ public class HttpUtilityEdgeCaseTests
+ {
+ [Fact]
+ public void UrlDecode_Byte_Array_With_Percent_Sequence()
+ {
+ var bytes = Encoding.ASCII.GetBytes("a%41%42%43z");
+ var result = HttpUtility.UrlDecode(bytes, 0, bytes.Length, Encoding.UTF8);
+ Assert.Equal("aABCz", result);
+ }
+
+ [Fact]
+ public void UrlDecodeToBytes_Byte_Array_Full()
+ {
+ var bytes = Encoding.ASCII.GetBytes("a%20b");
+ var result = HttpUtility.UrlDecodeToBytes(bytes);
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void ParseQueryString_Complex()
+ {
+ var result = HttpUtility.ParseQueryString("a=1&b=2&c=hello+world&d=%26");
+ Assert.Equal("1", result["a"]);
+ Assert.Equal("2", result["b"]);
+ Assert.Equal("hello world", result["c"]);
+ Assert.Equal("&", result["d"]);
+ }
+
+ [Fact]
+ public void UrlEncode_Byte_Array_Full()
+ {
+ var bytes = Encoding.UTF8.GetBytes("hello world!");
+ var result = HttpUtility.UrlEncode(bytes);
+ Assert.Contains("+", result);
+ // ! might or might not be encoded depending on implementation
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void UrlEncodeToBytes_Byte_Array_Full()
+ {
+ var bytes = Encoding.UTF8.GetBytes("hello world");
+ var result = HttpUtility.UrlEncodeToBytes(bytes);
+ Assert.NotNull(result);
+ Assert.True(result.Length > 0);
+ }
+
+ [Fact]
+ public void HtmlDecode_To_TextWriter_With_Entities()
+ {
+ var writer = new StringWriter();
+ HttpUtility.HtmlDecode("<b>hello</b>", writer);
+ Assert.Equal("hello", writer.ToString());
+ }
+
+ [Fact]
+ public void HtmlEncode_To_TextWriter_With_Entities()
+ {
+ var writer = new StringWriter();
+ HttpUtility.HtmlEncode("hello", writer);
+ var result = writer.ToString();
+ Assert.Contains("<", result);
+ Assert.Contains(">", result);
+ }
+
+ [Fact]
+ public void HtmlAttributeEncode_To_TextWriter_Null()
+ {
+ var writer = new StringWriter();
+ HttpUtility.HtmlAttributeEncode(null, writer);
+ Assert.Equal("", writer.ToString());
+ }
+ }
+
+ public class RestRequestAsyncHandleFinalTests
+ {
+ [Fact]
+ public void Abort_When_WebRequest_Is_Not_Null()
+ {
+ var handle = new RestRequestAsyncHandle();
+ // WebRequest is null, Abort should not throw
+ handle.Abort();
+ Assert.Null(handle.WebRequest);
+ }
+ }
+
+ public class MiscExtensionsFinalTests
+ {
+ [Fact]
+ public void AsString_NonNull_Bytes()
+ {
+ var bytes = Encoding.UTF8.GetBytes("test string");
+ var result = bytes.AsString();
+ Assert.Equal("test string", result);
+ }
+
+ [Fact]
+ public void AsString_Empty_Bytes()
+ {
+ var bytes = new byte[0];
+ var result = bytes.AsString();
+ Assert.Equal("", result);
+ }
+
+ [Fact]
+ public void ReadAsBytes_Empty_Stream()
+ {
+ using (var stream = new MemoryStream())
+ {
+ var result = stream.ReadAsBytes();
+ Assert.Empty(result);
+ }
+ }
+ }
+
+ public class JsonSerializerFinalTests
+ {
+ [Fact]
+ public void Serialize_With_Null_Property()
+ {
+ var serializer = new RestSharp.Serializers.JsonSerializer();
+ var result = serializer.Serialize(new ObjWithNullableField { Name = null, Count = 42 });
+ Assert.Contains("42", result);
+ }
+
+ [Fact]
+ public void DateFormat_Can_Be_Set()
+ {
+ var serializer = new RestSharp.Serializers.JsonSerializer();
+ serializer.DateFormat = "yyyy-MM-dd";
+ Assert.Equal("yyyy-MM-dd", serializer.DateFormat);
+ }
+
+ [Fact]
+ public void RootElement_Can_Be_Set()
+ {
+ var serializer = new RestSharp.Serializers.JsonSerializer();
+ serializer.RootElement = "root";
+ Assert.Equal("root", serializer.RootElement);
+ }
+
+ [Fact]
+ public void Namespace_Can_Be_Set()
+ {
+ var serializer = new RestSharp.Serializers.JsonSerializer();
+ serializer.Namespace = "ns";
+ Assert.Equal("ns", serializer.Namespace);
+ }
+ }
+
+ // Model classes
+ public class XmlAttrSimple
+ {
+ public string Name { get; set; }
+ public int Value { get; set; }
+ }
+
+ public class XmlWithAttr
+ {
+ public string Name { get; set; }
+ public int Value { get; set; }
+ }
+
+ public class XmlWithAttrStr
+ {
+ public string Name { get; set; }
+ public string Status { get; set; }
+ }
+
+ public class XmlNsSimple
+ {
+ public string Name { get; set; }
+ }
+
+ public class XmlWithDeserializeAs
+ {
+ [DeserializeAs(Name = "actual_name")]
+ public string TheName { get; set; }
+ }
+
+ public class XmlWithDeserializeAsAttr
+ {
+ [DeserializeAs(Name = "id", Attribute = true)]
+ public string Id { get; set; }
+ public string Name { get; set; }
+ }
+
+ public class XmlAttrListContainer
+ {
+ public List Items { get; set; }
+ }
+
+ public class XmlAttrListItem
+ {
+ public string Text { get; set; }
+ }
+
+ public class ObjWithNullableField
+ {
+ public string Name { get; set; }
+ public int Count { get; set; }
+ }
+}
diff --git a/RestSharp.Tests.Coverage/ResponseAndModelTests.cs b/RestSharp.Tests.Coverage/ResponseAndModelTests.cs
new file mode 100644
index 000000000..e7bcce07c
--- /dev/null
+++ b/RestSharp.Tests.Coverage/ResponseAndModelTests.cs
@@ -0,0 +1,485 @@
+using System;
+using System.Collections.Generic;
+using System.Net;
+using RestSharp;
+using RestSharp.Deserializers;
+using Xunit;
+
+namespace RestSharp.Tests.Coverage
+{
+ public class RestResponseTests
+ {
+ [Fact]
+ public void RestResponse_Has_Default_Values()
+ {
+ var response = new RestResponse();
+ Assert.NotNull(response.Headers);
+ Assert.NotNull(response.Cookies);
+ Assert.Equal(ResponseStatus.None, response.ResponseStatus);
+ }
+
+ [Fact]
+ public void RestResponse_Content_Can_Be_Set()
+ {
+ var response = new RestResponse();
+ response.Content = "{\"name\": \"test\"}";
+ Assert.Equal("{\"name\": \"test\"}", response.Content);
+ }
+
+ [Fact]
+ public void RestResponse_StatusCode_Can_Be_Set()
+ {
+ var response = new RestResponse();
+ response.StatusCode = HttpStatusCode.OK;
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ }
+
+ [Fact]
+ public void RestResponse_StatusDescription_Can_Be_Set()
+ {
+ var response = new RestResponse();
+ response.StatusDescription = "OK";
+ Assert.Equal("OK", response.StatusDescription);
+ }
+
+ [Fact]
+ public void RestResponse_ContentType_Can_Be_Set()
+ {
+ var response = new RestResponse();
+ response.ContentType = "application/json";
+ Assert.Equal("application/json", response.ContentType);
+ }
+
+ [Fact]
+ public void RestResponse_ContentLength_Can_Be_Set()
+ {
+ var response = new RestResponse();
+ response.ContentLength = 1024;
+ Assert.Equal(1024, response.ContentLength);
+ }
+
+ [Fact]
+ public void RestResponse_ContentEncoding_Can_Be_Set()
+ {
+ var response = new RestResponse();
+ response.ContentEncoding = "utf-8";
+ Assert.Equal("utf-8", response.ContentEncoding);
+ }
+
+ [Fact]
+ public void RestResponse_RawBytes_Can_Be_Set()
+ {
+ var response = new RestResponse();
+ var data = new byte[] { 1, 2, 3 };
+ response.RawBytes = data;
+ Assert.Equal(data, response.RawBytes);
+ }
+
+ [Fact]
+ public void RestResponse_ResponseUri_Can_Be_Set()
+ {
+ var response = new RestResponse();
+ var uri = new Uri("http://example.com");
+ response.ResponseUri = uri;
+ Assert.Equal(uri, response.ResponseUri);
+ }
+
+ [Fact]
+ public void RestResponse_Server_Can_Be_Set()
+ {
+ var response = new RestResponse();
+ response.Server = "nginx";
+ Assert.Equal("nginx", response.Server);
+ }
+
+ [Fact]
+ public void RestResponse_ErrorMessage_Can_Be_Set()
+ {
+ var response = new RestResponse();
+ response.ErrorMessage = "Connection failed";
+ Assert.Equal("Connection failed", response.ErrorMessage);
+ }
+
+ [Fact]
+ public void RestResponse_ErrorException_Can_Be_Set()
+ {
+ var response = new RestResponse();
+ var ex = new Exception("test error");
+ response.ErrorException = ex;
+ Assert.Equal(ex, response.ErrorException);
+ }
+
+ [Fact]
+ public void RestResponse_Request_Can_Be_Set()
+ {
+ var response = new RestResponse();
+ var request = new RestRequest();
+ response.Request = request;
+ Assert.Equal(request, response.Request);
+ }
+
+ [Fact]
+ public void RestResponse_ResponseStatus_Can_Be_Set()
+ {
+ var response = new RestResponse();
+ response.ResponseStatus = ResponseStatus.Completed;
+ Assert.Equal(ResponseStatus.Completed, response.ResponseStatus);
+
+ response.ResponseStatus = ResponseStatus.Error;
+ Assert.Equal(ResponseStatus.Error, response.ResponseStatus);
+
+ response.ResponseStatus = ResponseStatus.TimedOut;
+ Assert.Equal(ResponseStatus.TimedOut, response.ResponseStatus);
+
+ response.ResponseStatus = ResponseStatus.Aborted;
+ Assert.Equal(ResponseStatus.Aborted, response.ResponseStatus);
+ }
+
+ [Fact]
+ public void GenericRestResponse_Has_Data_Property()
+ {
+ var response = new RestResponse();
+ response.Data = new TestData { Name = "test", Value = 42 };
+ Assert.Equal("test", response.Data.Name);
+ Assert.Equal(42, response.Data.Value);
+ }
+
+ [Fact]
+ public void GenericRestResponse_Inherits_Base_Properties()
+ {
+ var response = new RestResponse();
+ response.Content = "content";
+ response.StatusCode = HttpStatusCode.NotFound;
+ Assert.Equal("content", response.Content);
+ Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
+ }
+
+ private class TestData
+ {
+ public string Name { get; set; }
+ public int Value { get; set; }
+ }
+ }
+
+ public class ParameterTests
+ {
+ [Fact]
+ public void Parameter_Properties_Can_Be_Set()
+ {
+ var param = new Parameter();
+ param.Name = "test";
+ param.Value = "value";
+ param.Type = ParameterType.GetOrPost;
+
+ Assert.Equal("test", param.Name);
+ Assert.Equal("value", param.Value);
+ Assert.Equal(ParameterType.GetOrPost, param.Type);
+ }
+
+ [Fact]
+ public void Parameter_ToString_Returns_Name_Equals_Value()
+ {
+ var param = new Parameter();
+ param.Name = "key";
+ param.Value = "val";
+ param.Type = ParameterType.GetOrPost;
+
+ var str = param.ToString();
+ Assert.Equal("key=val", str);
+ }
+
+ [Fact]
+ public void Parameter_Types_Cover_All_Enum_Values()
+ {
+ Assert.Equal(0, (int)ParameterType.Cookie);
+ Assert.Equal(1, (int)ParameterType.GetOrPost);
+ Assert.Equal(2, (int)ParameterType.UrlSegment);
+ Assert.Equal(3, (int)ParameterType.HttpHeader);
+ Assert.Equal(4, (int)ParameterType.RequestBody);
+ }
+ }
+
+ public class FileParameterTests
+ {
+ [Fact]
+ public void Create_From_Bytes_Sets_Properties()
+ {
+ var data = new byte[] { 1, 2, 3, 4 };
+ var fp = FileParameter.Create("file", data, "test.bin", "application/octet-stream");
+
+ Assert.Equal("file", fp.Name);
+ Assert.Equal("test.bin", fp.FileName);
+ Assert.Equal("application/octet-stream", fp.ContentType);
+ Assert.Equal(4, fp.ContentLength);
+ Assert.NotNull(fp.Writer);
+ }
+
+ [Fact]
+ public void Create_From_Bytes_Default_ContentType()
+ {
+ var data = new byte[] { 1, 2, 3 };
+ var fp = FileParameter.Create("file", data, "test.bin");
+
+ Assert.Null(fp.ContentType);
+ }
+
+ [Fact]
+ public void Create_From_Bytes_3_Params()
+ {
+ var data = new byte[] { 1, 2, 3 };
+ var fp = FileParameter.Create("file", data, "test.bin");
+
+ Assert.Equal("file", fp.Name);
+ Assert.Equal("test.bin", fp.FileName);
+ Assert.Equal(3, fp.ContentLength);
+ }
+
+ [Fact]
+ public void Writer_Writes_Correct_Data()
+ {
+ var data = new byte[] { 10, 20, 30 };
+ var fp = FileParameter.Create("file", data, "test.bin");
+
+ using (var stream = new System.IO.MemoryStream())
+ {
+ fp.Writer(stream);
+ Assert.Equal(data, stream.ToArray());
+ }
+ }
+
+ [Fact]
+ public void FileParameter_Properties_Can_Be_Set()
+ {
+ var fp = new FileParameter();
+ Action writer = s => { };
+ fp.Name = "test";
+ fp.FileName = "file.txt";
+ fp.ContentType = "text/plain";
+ fp.ContentLength = 100;
+ fp.Writer = writer;
+
+ Assert.Equal("test", fp.Name);
+ Assert.Equal("file.txt", fp.FileName);
+ Assert.Equal("text/plain", fp.ContentType);
+ Assert.Equal(100, fp.ContentLength);
+ Assert.Equal(writer, fp.Writer);
+ }
+ }
+
+ public class HttpResponseTests
+ {
+ [Fact]
+ public void HttpResponse_Has_Default_Values()
+ {
+ var response = new HttpResponse();
+ Assert.NotNull(response.Headers);
+ Assert.NotNull(response.Cookies);
+ Assert.Equal(ResponseStatus.None, response.ResponseStatus);
+ }
+
+ [Fact]
+ public void HttpResponse_Properties_Can_Be_Set()
+ {
+ var response = new HttpResponse();
+ response.ContentEncoding = "utf-8";
+ response.ContentLength = 4;
+ response.ContentType = "text/plain";
+ response.ErrorMessage = "error";
+ response.ErrorException = new Exception("ex");
+ response.RawBytes = System.Text.Encoding.UTF8.GetBytes("body");
+ response.ResponseUri = new Uri("http://example.com");
+ response.Server = "Apache";
+ response.StatusCode = HttpStatusCode.OK;
+ response.StatusDescription = "OK";
+ response.ResponseStatus = ResponseStatus.Completed;
+
+ Assert.Equal("body", response.Content);
+ Assert.Equal("utf-8", response.ContentEncoding);
+ Assert.Equal(4, response.ContentLength);
+ Assert.Equal("text/plain", response.ContentType);
+ Assert.Equal("error", response.ErrorMessage);
+ Assert.NotNull(response.ErrorException);
+ Assert.Equal(4, response.RawBytes.Length);
+ Assert.Equal("http://example.com/", response.ResponseUri.ToString());
+ Assert.Equal("Apache", response.Server);
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Equal("OK", response.StatusDescription);
+ Assert.Equal(ResponseStatus.Completed, response.ResponseStatus);
+ }
+
+ [Fact]
+ public void HttpResponse_Content_Is_Lazy_Loaded_From_RawBytes()
+ {
+ var response = new HttpResponse();
+ response.RawBytes = System.Text.Encoding.UTF8.GetBytes("hello world");
+ Assert.Equal("hello world", response.Content);
+ }
+
+ [Fact]
+ public void HttpResponse_Content_Returns_Empty_When_RawBytes_Null()
+ {
+ var response = new HttpResponse();
+ // When RawBytes is null, AsString() returns empty string
+ var content = response.Content;
+ Assert.True(content == null || content == "");
+ }
+ }
+
+ public class HttpCookieTests
+ {
+ [Fact]
+ public void HttpCookie_Properties_Can_Be_Set()
+ {
+ var cookie = new HttpCookie();
+ cookie.Comment = "test cookie";
+ cookie.CommentUri = new Uri("http://example.com");
+ cookie.Discard = true;
+ cookie.Domain = "example.com";
+ cookie.Expired = false;
+ cookie.Expires = new DateTime(2025, 1, 1);
+ cookie.HttpOnly = true;
+ cookie.Name = "session";
+ cookie.Path = "/";
+ cookie.Port = "80";
+ cookie.Secure = true;
+ cookie.TimeStamp = DateTime.Now;
+ cookie.Value = "abc123";
+ cookie.Version = 1;
+
+ Assert.Equal("test cookie", cookie.Comment);
+ Assert.Equal("example.com", cookie.Domain);
+ Assert.True(cookie.Discard);
+ Assert.False(cookie.Expired);
+ Assert.True(cookie.HttpOnly);
+ Assert.Equal("session", cookie.Name);
+ Assert.Equal("/", cookie.Path);
+ Assert.True(cookie.Secure);
+ Assert.Equal("abc123", cookie.Value);
+ Assert.Equal(1, cookie.Version);
+ }
+ }
+
+ public class RestResponseCookieTests
+ {
+ [Fact]
+ public void RestResponseCookie_Properties_Can_Be_Set()
+ {
+ var cookie = new RestResponseCookie();
+ cookie.Comment = "test";
+ cookie.CommentUri = new Uri("http://example.com");
+ cookie.Discard = true;
+ cookie.Domain = "example.com";
+ cookie.Expired = true;
+ cookie.Expires = new DateTime(2024, 6, 1);
+ cookie.HttpOnly = true;
+ cookie.Name = "auth";
+ cookie.Path = "/api";
+ cookie.Port = "443";
+ cookie.Secure = true;
+ cookie.TimeStamp = DateTime.UtcNow;
+ cookie.Value = "token123";
+ cookie.Version = 2;
+
+ Assert.Equal("test", cookie.Comment);
+ Assert.Equal("example.com", cookie.Domain);
+ Assert.True(cookie.Discard);
+ Assert.True(cookie.Expired);
+ Assert.True(cookie.HttpOnly);
+ Assert.Equal("auth", cookie.Name);
+ Assert.Equal("/api", cookie.Path);
+ Assert.Equal("443", cookie.Port);
+ Assert.True(cookie.Secure);
+ Assert.Equal("token123", cookie.Value);
+ Assert.Equal(2, cookie.Version);
+ }
+ }
+
+ public class HttpHeaderTests
+ {
+ [Fact]
+ public void HttpHeader_Properties_Can_Be_Set()
+ {
+ var header = new HttpHeader();
+ header.Name = "Content-Type";
+ header.Value = "application/json";
+
+ Assert.Equal("Content-Type", header.Name);
+ Assert.Equal("application/json", header.Value);
+ }
+ }
+
+ public class HttpParameterTests
+ {
+ [Fact]
+ public void HttpParameter_Properties_Can_Be_Set()
+ {
+ var param = new HttpParameter();
+ param.Name = "q";
+ param.Value = "search term";
+
+ Assert.Equal("q", param.Name);
+ Assert.Equal("search term", param.Value);
+ }
+ }
+
+ public class HttpFileTests
+ {
+ [Fact]
+ public void HttpFile_Properties_Can_Be_Set()
+ {
+ var file = new HttpFile();
+ file.Name = "upload";
+ file.FileName = "document.pdf";
+ file.ContentType = "application/pdf";
+ file.ContentLength = 1024;
+ file.Writer = s => { };
+
+ Assert.Equal("upload", file.Name);
+ Assert.Equal("document.pdf", file.FileName);
+ Assert.Equal("application/pdf", file.ContentType);
+ Assert.Equal(1024, file.ContentLength);
+ Assert.NotNull(file.Writer);
+ }
+ }
+
+ public class RestRequestAsyncHandleTests
+ {
+ [Fact]
+ public void Default_Constructor_Creates_Handle()
+ {
+ var handle = new RestRequestAsyncHandle();
+ Assert.Null(handle.WebRequest);
+ }
+
+ [Fact]
+ public void Abort_Does_Not_Throw_When_WebRequest_Is_Null()
+ {
+ var handle = new RestRequestAsyncHandle();
+ handle.Abort(); // should not throw
+ }
+ }
+
+ public class DeserializeAsAttributeTests
+ {
+ [Fact]
+ public void DeserializeAsAttribute_Can_Be_Created()
+ {
+ var attr = new DeserializeAsAttribute();
+ Assert.NotNull(attr);
+ }
+
+ [Fact]
+ public void DeserializeAsAttribute_Name_Can_Be_Set()
+ {
+ var attr = new DeserializeAsAttribute { Name = "custom" };
+ Assert.Equal("custom", attr.Name);
+ }
+
+ [Fact]
+ public void DeserializeAsAttribute_Attribute_Can_Be_Set()
+ {
+ var attr = new DeserializeAsAttribute { Attribute = true };
+ Assert.True(attr.Attribute);
+ }
+ }
+}
diff --git a/RestSharp.Tests.Coverage/RestClientIntegrationTests.cs b/RestSharp.Tests.Coverage/RestClientIntegrationTests.cs
new file mode 100644
index 000000000..efffa9030
--- /dev/null
+++ b/RestSharp.Tests.Coverage/RestClientIntegrationTests.cs
@@ -0,0 +1,664 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+using RestSharp;
+using RestSharp.Deserializers;
+using Xunit;
+
+namespace RestSharp.Tests.Coverage
+{
+ ///
+ /// Tests that exercise RestClient's internal methods (ConfigureHttp, ConvertToRestResponse, etc.)
+ /// through the Execute method with a fake HTTP implementation.
+ ///
+ public class RestClientIntegrationTests
+ {
+ [Fact]
+ public void Execute_With_FakeHttp_Returns_Response()
+ {
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactory(new HttpResponse
+ {
+ RawBytes = Encoding.UTF8.GetBytes("{\"name\":\"test\"}"),
+ ContentType = "application/json",
+ StatusCode = HttpStatusCode.OK,
+ StatusDescription = "OK",
+ ContentEncoding = "utf-8",
+ ContentLength = 15,
+ ResponseUri = new Uri("http://example.com/api"),
+ Server = "TestServer",
+ ResponseStatus = ResponseStatus.Completed
+ });
+
+ var request = new RestRequest("api", Method.GET);
+ var response = client.Execute(request);
+
+ Assert.Equal("{\"name\":\"test\"}", response.Content);
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Equal("OK", response.StatusDescription);
+ Assert.Equal("TestServer", response.Server);
+ Assert.Equal(ResponseStatus.Completed, response.ResponseStatus);
+ }
+
+ [Fact]
+ public void Execute_With_POST_Uses_PostMethod()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.POST);
+ request.AddParameter("data", "value");
+ var response = client.Execute(request);
+
+ Assert.Equal("POST", fakeHttp.LastMethod);
+ }
+
+ [Fact]
+ public void Execute_With_PUT_Uses_PutMethod()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.PUT);
+ client.Execute(request);
+
+ Assert.Equal("PUT", fakeHttp.LastMethod);
+ }
+
+ [Fact]
+ public void Execute_With_DELETE_Uses_DeleteMethod()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.DELETE);
+ client.Execute(request);
+
+ Assert.Equal("DELETE", fakeHttp.LastMethod);
+ }
+
+ [Fact]
+ public void Execute_With_HEAD_Uses_HeadMethod()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.HEAD);
+ client.Execute(request);
+
+ Assert.Equal("HEAD", fakeHttp.LastMethod);
+ }
+
+ [Fact]
+ public void Execute_With_OPTIONS_Uses_OptionsMethod()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.OPTIONS);
+ client.Execute(request);
+
+ Assert.Equal("OPTIONS", fakeHttp.LastMethod);
+ }
+
+ [Fact]
+ public void Execute_With_PATCH_Uses_PatchMethod()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.PATCH);
+ client.Execute(request);
+
+ Assert.Equal("PATCH", fakeHttp.LastMethod);
+ }
+
+ [Fact]
+ public void Execute_Configures_Headers_From_Request()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.GET);
+ request.AddHeader("X-Custom", "CustomValue");
+ client.Execute(request);
+
+ Assert.Contains(fakeHttp.Headers, h => h.Name == "X-Custom" && h.Value == "CustomValue");
+ }
+
+ [Fact]
+ public void Execute_Configures_Cookies_From_Request()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.GET);
+ request.AddCookie("session", "abc");
+ client.Execute(request);
+
+ Assert.Contains(fakeHttp.Cookies, c => c.Name == "session" && c.Value == "abc");
+ }
+
+ [Fact]
+ public void Execute_Configures_Parameters_From_Request()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.POST);
+ request.AddParameter("key", "val");
+ client.Execute(request);
+
+ Assert.Contains(fakeHttp.Parameters, p => p.Name == "key" && p.Value == "val");
+ }
+
+ [Fact]
+ public void Execute_Configures_RequestBody_From_Request()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.POST);
+ request.RequestFormat = DataFormat.Json;
+ request.AddBody(new { Name = "test" });
+ client.Execute(request);
+
+ Assert.NotNull(fakeHttp.RequestBody);
+ Assert.Contains("test", fakeHttp.RequestBody);
+ }
+
+ [Fact]
+ public void Execute_Sets_UserAgent()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.UserAgent = "TestAgent/1.0";
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.GET);
+ client.Execute(request);
+
+ Assert.Equal("TestAgent/1.0", fakeHttp.UserAgent);
+ }
+
+ [Fact]
+ public void Execute_Sets_Timeout_From_Request()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.Timeout = 5000;
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.GET);
+ request.Timeout = 3000;
+ client.Execute(request);
+
+ Assert.Equal(3000, fakeHttp.Timeout);
+ }
+
+ [Fact]
+ public void Execute_Sets_Timeout_From_Client_When_Request_Zero()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.Timeout = 5000;
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.GET);
+ client.Execute(request);
+
+ Assert.Equal(5000, fakeHttp.Timeout);
+ }
+
+ [Fact]
+ public void Execute_Merges_DefaultParameters()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.AddDefaultHeader("X-Default", "default-value");
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.GET);
+ client.Execute(request);
+
+ Assert.Contains(fakeHttp.Headers, h => h.Name == "X-Default" && h.Value == "default-value");
+ }
+
+ [Fact]
+ public void Execute_Request_Overrides_DefaultParameters()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.AddDefaultHeader("X-Custom", "default");
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.GET);
+ request.AddHeader("X-Custom", "override");
+ client.Execute(request);
+
+ var customHeaders = fakeHttp.Headers.Where(h => h.Name == "X-Custom").ToList();
+ Assert.Single(customHeaders);
+ Assert.Equal("override", customHeaders[0].Value);
+ }
+
+ [Fact]
+ public void Execute_With_Authenticator_Authenticates_Request()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.Authenticator = new HttpBasicAuthenticator("user", "pass");
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.GET);
+ client.Execute(request);
+
+ Assert.Contains(fakeHttp.Headers, h => h.Name == "Authorization");
+ }
+
+ [Fact]
+ public void Execute_Increments_Request_Attempts()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.GET);
+ Assert.Equal(0, request.Attempts);
+ client.Execute(request);
+ Assert.Equal(1, request.Attempts);
+ }
+
+ [Fact]
+ public void Execute_Handles_Exception_Sets_Error_Status()
+ {
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new ThrowingHttpFactory();
+
+ var request = new RestRequest("api", Method.GET);
+ var response = client.Execute(request);
+
+ Assert.Equal(ResponseStatus.Error, response.ResponseStatus);
+ Assert.NotNull(response.ErrorMessage);
+ Assert.NotNull(response.ErrorException);
+ }
+
+ [Fact]
+ public void Execute_Generic_Returns_Deserialized_Data()
+ {
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactory(new HttpResponse
+ {
+ RawBytes = Encoding.UTF8.GetBytes("{\"Name\":\"test\",\"Value\":42}"),
+ ContentType = "application/json",
+ StatusCode = HttpStatusCode.OK,
+ ResponseStatus = ResponseStatus.Completed
+ });
+
+ var request = new RestRequest("api", Method.GET);
+ var response = client.Execute(request);
+
+ Assert.NotNull(response.Data);
+ Assert.Equal("test", response.Data.Name);
+ Assert.Equal(42, response.Data.Value);
+ }
+
+ [Fact]
+ public void ConvertToRestResponse_Copies_Headers()
+ {
+ var client = new RestClient("http://example.com");
+ var fakeResponse = new HttpResponse
+ {
+ RawBytes = Encoding.UTF8.GetBytes("body"),
+ ContentType = "text/plain",
+ StatusCode = HttpStatusCode.OK,
+ ResponseStatus = ResponseStatus.Completed
+ };
+ fakeResponse.Headers.Add(new HttpHeader { Name = "X-Test", Value = "123" });
+
+ client.HttpFactory = new FakeHttpFactory(fakeResponse);
+ var request = new RestRequest("api", Method.GET);
+ var response = client.Execute(request);
+
+ Assert.Contains(response.Headers, h => h.Name == "X-Test" && h.Value.ToString() == "123");
+ }
+
+ [Fact]
+ public void ConvertToRestResponse_Copies_Cookies()
+ {
+ var client = new RestClient("http://example.com");
+ var fakeResponse = new HttpResponse
+ {
+ RawBytes = Encoding.UTF8.GetBytes("body"),
+ ContentType = "text/plain",
+ StatusCode = HttpStatusCode.OK,
+ ResponseStatus = ResponseStatus.Completed
+ };
+ fakeResponse.Cookies.Add(new HttpCookie
+ {
+ Name = "session",
+ Value = "abc",
+ Domain = "example.com",
+ Path = "/",
+ HttpOnly = true,
+ Secure = true
+ });
+
+ client.HttpFactory = new FakeHttpFactory(fakeResponse);
+ var request = new RestRequest("api", Method.GET);
+ var response = client.Execute(request);
+
+ Assert.Single(response.Cookies);
+ Assert.Equal("session", response.Cookies[0].Name);
+ Assert.Equal("abc", response.Cookies[0].Value);
+ Assert.Equal("example.com", response.Cookies[0].Domain);
+ Assert.True(response.Cookies[0].HttpOnly);
+ Assert.True(response.Cookies[0].Secure);
+ }
+
+ [Fact]
+ public void Execute_Sets_FollowRedirects()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.FollowRedirects = false;
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.GET);
+ client.Execute(request);
+
+ Assert.False(fakeHttp.FollowRedirects);
+ }
+
+ [Fact]
+ public void Execute_Sets_MaxRedirects()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.MaxRedirects = 3;
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.GET);
+ client.Execute(request);
+
+ Assert.Equal(3, fakeHttp.MaxRedirects);
+ }
+
+ [Fact]
+ public void Execute_Sets_CookieContainer()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ var container = new CookieContainer();
+ client.CookieContainer = container;
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.GET);
+ client.Execute(request);
+
+ Assert.Equal(container, fakeHttp.CookieContainer);
+ }
+
+ [Fact]
+ public void Execute_Sets_Proxy()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ var proxy = new WebProxy("http://proxy.example.com");
+ client.Proxy = proxy;
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.GET);
+ client.Execute(request);
+
+ Assert.Equal(proxy, fakeHttp.Proxy);
+ }
+
+ [Fact]
+ public void Execute_Sets_Credentials_From_Request()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.GET);
+ var creds = new NetworkCredential("user", "pass");
+ request.Credentials = creds;
+ client.Execute(request);
+
+ Assert.Equal(creds, fakeHttp.Credentials);
+ }
+
+ [Fact]
+ public void Execute_Configures_Files_From_Request()
+ {
+ var fakeHttp = new FakeHttp();
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactoryInstance(fakeHttp);
+
+ var request = new RestRequest("api", Method.POST);
+ request.AddFile("file", new byte[] { 1, 2, 3 }, "test.bin");
+ client.Execute(request);
+
+ Assert.Single(fakeHttp.Files);
+ Assert.Equal("file", fakeHttp.Files[0].Name);
+ }
+
+ [Fact]
+ public void DownloadData_Returns_RawBytes()
+ {
+ var rawData = new byte[] { 10, 20, 30 };
+ var client = new RestClient("http://example.com");
+ client.HttpFactory = new FakeHttpFactory(new HttpResponse
+ {
+ ContentType = "application/octet-stream",
+ RawBytes = rawData,
+ StatusCode = HttpStatusCode.OK,
+ ResponseStatus = ResponseStatus.Completed
+ });
+
+ var request = new RestRequest("data", Method.GET);
+ var result = client.DownloadData(request);
+
+ Assert.Equal(rawData, result);
+ }
+
+ public class SimpleData
+ {
+ public string Name { get; set; }
+ public int Value { get; set; }
+ }
+ }
+
+ #region Fake HTTP implementations
+
+ public class FakeHttp : IHttp
+ {
+ public string LastMethod { get; private set; }
+ public CookieContainer CookieContainer { get; set; }
+ public ICredentials Credentials { get; set; }
+ public string UserAgent { get; set; }
+ public int Timeout { get; set; }
+ public bool FollowRedirects { get; set; }
+ public System.Security.Cryptography.X509Certificates.X509CertificateCollection ClientCertificates { get; set; }
+ public int? MaxRedirects { get; set; }
+ public IList Headers { get; private set; }
+ public IList Parameters { get; private set; }
+ public IList Files { get; private set; }
+ public IList Cookies { get; private set; }
+ public string RequestBody { get; set; }
+ public string RequestContentType { get; set; }
+ public Uri Url { get; set; }
+ public IWebProxy Proxy { get; set; }
+
+ public FakeHttp()
+ {
+ Headers = new List();
+ Parameters = new List();
+ Files = new List();
+ Cookies = new List();
+ }
+
+ private HttpResponse MakeResponse(string method)
+ {
+ LastMethod = method;
+ return new HttpResponse { ResponseStatus = ResponseStatus.Completed, StatusCode = HttpStatusCode.OK, RawBytes = new byte[0] };
+ }
+
+ public HttpResponse Delete() => MakeResponse("DELETE");
+ public HttpResponse Get() => MakeResponse("GET");
+ public HttpResponse Head() => MakeResponse("HEAD");
+ public HttpResponse Options() => MakeResponse("OPTIONS");
+ public HttpResponse Post() => MakeResponse("POST");
+ public HttpResponse Put() => MakeResponse("PUT");
+ public HttpResponse Patch() => MakeResponse("PATCH");
+
+ public HttpWebRequest DeleteAsync(Action action) { action(MakeResponse("DELETE")); return null; }
+ public HttpWebRequest GetAsync(Action action) { action(MakeResponse("GET")); return null; }
+ public HttpWebRequest HeadAsync(Action action) { action(MakeResponse("HEAD")); return null; }
+ public HttpWebRequest OptionsAsync(Action action) { action(MakeResponse("OPTIONS")); return null; }
+ public HttpWebRequest PostAsync(Action action) { action(MakeResponse("POST")); return null; }
+ public HttpWebRequest PutAsync(Action action) { action(MakeResponse("PUT")); return null; }
+ public HttpWebRequest PatchAsync(Action action) { action(MakeResponse("PATCH")); return null; }
+ }
+
+ public class FakeHttpFactory : IHttpFactory
+ {
+ private readonly HttpResponse _response;
+
+ public FakeHttpFactory(HttpResponse response)
+ {
+ _response = response;
+ }
+
+ public IHttp Create()
+ {
+ return new FakeHttpWithResponse(_response);
+ }
+ }
+
+ public class FakeHttpWithResponse : IHttp
+ {
+ private readonly HttpResponse _response;
+
+ public FakeHttpWithResponse(HttpResponse response)
+ {
+ _response = response;
+ Headers = new List();
+ Parameters = new List();
+ Files = new List();
+ Cookies = new List();
+ }
+
+ public CookieContainer CookieContainer { get; set; }
+ public ICredentials Credentials { get; set; }
+ public string UserAgent { get; set; }
+ public int Timeout { get; set; }
+ public bool FollowRedirects { get; set; }
+ public System.Security.Cryptography.X509Certificates.X509CertificateCollection ClientCertificates { get; set; }
+ public int? MaxRedirects { get; set; }
+ public IList Headers { get; private set; }
+ public IList Parameters { get; private set; }
+ public IList Files { get; private set; }
+ public IList Cookies { get; private set; }
+ public string RequestBody { get; set; }
+ public string RequestContentType { get; set; }
+ public Uri Url { get; set; }
+ public IWebProxy Proxy { get; set; }
+
+ public HttpResponse Delete() => _response;
+ public HttpResponse Get() => _response;
+ public HttpResponse Head() => _response;
+ public HttpResponse Options() => _response;
+ public HttpResponse Post() => _response;
+ public HttpResponse Put() => _response;
+ public HttpResponse Patch() => _response;
+
+ public HttpWebRequest DeleteAsync(Action action) { action(_response); return null; }
+ public HttpWebRequest GetAsync(Action action) { action(_response); return null; }
+ public HttpWebRequest HeadAsync(Action action) { action(_response); return null; }
+ public HttpWebRequest OptionsAsync(Action action) { action(_response); return null; }
+ public HttpWebRequest PostAsync(Action action) { action(_response); return null; }
+ public HttpWebRequest PutAsync(Action action) { action(_response); return null; }
+ public HttpWebRequest PatchAsync(Action action) { action(_response); return null; }
+ }
+
+ public class FakeHttpFactoryInstance : IHttpFactory
+ {
+ private readonly IHttp _instance;
+
+ public FakeHttpFactoryInstance(IHttp instance)
+ {
+ _instance = instance;
+ }
+
+ public IHttp Create()
+ {
+ return _instance;
+ }
+ }
+
+ public class ThrowingHttpFactory : IHttpFactory
+ {
+ public IHttp Create()
+ {
+ return new ThrowingHttp();
+ }
+ }
+
+ public class ThrowingHttp : IHttp
+ {
+ public CookieContainer CookieContainer { get; set; }
+ public ICredentials Credentials { get; set; }
+ public string UserAgent { get; set; }
+ public int Timeout { get; set; }
+ public bool FollowRedirects { get; set; }
+ public System.Security.Cryptography.X509Certificates.X509CertificateCollection ClientCertificates { get; set; }
+ public int? MaxRedirects { get; set; }
+ public IList Headers { get; private set; }
+ public IList Parameters { get; private set; }
+ public IList Files { get; private set; }
+ public IList Cookies { get; private set; }
+ public string RequestBody { get; set; }
+ public string RequestContentType { get; set; }
+ public Uri Url { get; set; }
+ public IWebProxy Proxy { get; set; }
+
+ public ThrowingHttp()
+ {
+ Headers = new List();
+ Parameters = new List();
+ Files = new List();
+ Cookies = new List();
+ }
+
+ public HttpResponse Delete() => throw new Exception("Test exception");
+ public HttpResponse Get() => throw new Exception("Test exception");
+ public HttpResponse Head() => throw new Exception("Test exception");
+ public HttpResponse Options() => throw new Exception("Test exception");
+ public HttpResponse Post() => throw new Exception("Test exception");
+ public HttpResponse Put() => throw new Exception("Test exception");
+ public HttpResponse Patch() => throw new Exception("Test exception");
+
+ public HttpWebRequest DeleteAsync(Action action) => throw new Exception("Test exception");
+ public HttpWebRequest GetAsync(Action action) => throw new Exception("Test exception");
+ public HttpWebRequest HeadAsync(Action action) => throw new Exception("Test exception");
+ public HttpWebRequest OptionsAsync(Action action) => throw new Exception("Test exception");
+ public HttpWebRequest PostAsync(Action action) => throw new Exception("Test exception");
+ public HttpWebRequest PutAsync(Action action) => throw new Exception("Test exception");
+ public HttpWebRequest PatchAsync(Action action) => throw new Exception("Test exception");
+ }
+
+ #endregion
+}
diff --git a/RestSharp.Tests.Coverage/RestClientTests.cs b/RestSharp.Tests.Coverage/RestClientTests.cs
new file mode 100644
index 000000000..087dff31d
--- /dev/null
+++ b/RestSharp.Tests.Coverage/RestClientTests.cs
@@ -0,0 +1,288 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using RestSharp;
+using RestSharp.Deserializers;
+using Xunit;
+
+namespace RestSharp.Tests.Coverage
+{
+ public class RestClientTests
+ {
+ [Fact]
+ public void Default_Constructor_Sets_Default_UserAgent()
+ {
+ var client = new RestClient();
+ Assert.NotNull(client.UserAgent);
+ Assert.StartsWith("RestSharp", client.UserAgent);
+ }
+
+ [Fact]
+ public void Default_Constructor_Sets_FollowRedirects_True()
+ {
+ var client = new RestClient();
+ Assert.True(client.FollowRedirects);
+ }
+
+ [Fact]
+ public void Constructor_With_BaseUrl_Sets_BaseUrl()
+ {
+ var client = new RestClient("http://example.com");
+ Assert.Equal("http://example.com", client.BaseUrl);
+ }
+
+ [Fact]
+ public void BaseUrl_Strips_Trailing_Slash()
+ {
+ var client = new RestClient();
+ client.BaseUrl = "http://example.com/";
+ Assert.Equal("http://example.com", client.BaseUrl);
+ }
+
+ [Fact]
+ public void DefaultParameters_Is_Not_Null()
+ {
+ var client = new RestClient();
+ Assert.NotNull(client.DefaultParameters);
+ }
+
+ [Fact]
+ public void AddDefaultParameter_Adds_To_DefaultParameters()
+ {
+ var client = new RestClient();
+ client.AddDefaultParameter("key", "value");
+ Assert.Single(client.DefaultParameters);
+ Assert.Equal("key", client.DefaultParameters[0].Name);
+ }
+
+ [Fact]
+ public void AddDefaultParameter_With_Type_Adds_Correct_Type()
+ {
+ var client = new RestClient();
+ client.AddDefaultParameter("X-Custom", "value", ParameterType.HttpHeader);
+ Assert.Equal(ParameterType.HttpHeader, client.DefaultParameters[0].Type);
+ }
+
+ [Fact]
+ public void AddDefaultParameter_RequestBody_Throws()
+ {
+ var client = new RestClient();
+ var p = new Parameter { Name = "body", Value = "data", Type = ParameterType.RequestBody };
+ Assert.Throws(() => client.AddDefaultParameter(p));
+ }
+
+ [Fact]
+ public void AddDefaultHeader_Adds_HttpHeader()
+ {
+ var client = new RestClient();
+ client.AddDefaultHeader("Authorization", "Bearer token");
+ var param = client.DefaultParameters.First();
+ Assert.Equal("Authorization", param.Name);
+ Assert.Equal(ParameterType.HttpHeader, param.Type);
+ }
+
+ [Fact]
+ public void AddDefaultUrlSegment_Adds_UrlSegment()
+ {
+ var client = new RestClient();
+ client.AddDefaultUrlSegment("version", "v2");
+ var param = client.DefaultParameters.First();
+ Assert.Equal("version", param.Name);
+ Assert.Equal(ParameterType.UrlSegment, param.Type);
+ }
+
+ [Fact]
+ public void AddHandler_Registers_Deserializer()
+ {
+ var client = new RestClient();
+ client.ClearHandlers();
+ client.AddHandler("text/csv", new JsonDeserializer());
+ // Verify by building a URI (handlers are used internally)
+ Assert.NotNull(client);
+ }
+
+ [Fact]
+ public void RemoveHandler_Removes_Handler()
+ {
+ var client = new RestClient();
+ client.RemoveHandler("application/json");
+ // Should not throw and handler should be removed
+ Assert.NotNull(client);
+ }
+
+ [Fact]
+ public void ClearHandlers_Removes_All_Handlers()
+ {
+ var client = new RestClient();
+ client.ClearHandlers();
+ Assert.NotNull(client);
+ }
+
+ [Fact]
+ public void Timeout_Can_Be_Set()
+ {
+ var client = new RestClient();
+ client.Timeout = 30000;
+ Assert.Equal(30000, client.Timeout);
+ }
+
+ [Fact]
+ public void Authenticator_Can_Be_Set()
+ {
+ var client = new RestClient();
+ var auth = new HttpBasicAuthenticator("user", "pass");
+ client.Authenticator = auth;
+ Assert.Equal(auth, client.Authenticator);
+ }
+
+ [Fact]
+ public void CookieContainer_Can_Be_Set()
+ {
+ var client = new RestClient();
+ var container = new CookieContainer();
+ client.CookieContainer = container;
+ Assert.Equal(container, client.CookieContainer);
+ }
+
+ [Fact]
+ public void MaxRedirects_Can_Be_Set()
+ {
+ var client = new RestClient();
+ client.MaxRedirects = 10;
+ Assert.Equal(10, client.MaxRedirects);
+ }
+
+ [Fact]
+ public void UserAgent_Can_Be_Set()
+ {
+ var client = new RestClient();
+ client.UserAgent = "Custom/1.0";
+ Assert.Equal("Custom/1.0", client.UserAgent);
+ }
+
+ [Fact]
+ public void UseSynchronizationContext_Default_Is_False()
+ {
+ var client = new RestClient();
+ Assert.False(client.UseSynchronizationContext);
+ }
+
+ [Fact]
+ public void BuildUri_With_BaseUrl_And_Resource()
+ {
+ var client = new RestClient("http://example.com");
+ var request = new RestRequest("api/users");
+ var uri = client.BuildUri(request);
+ Assert.Equal("http://example.com/api/users", uri.ToString());
+ }
+
+ [Fact]
+ public void BuildUri_With_Empty_Resource()
+ {
+ var client = new RestClient("http://example.com");
+ var request = new RestRequest();
+ var uri = client.BuildUri(request);
+ Assert.Equal("http://example.com/", uri.ToString());
+ }
+
+ [Fact]
+ public void BuildUri_With_QueryString_For_GET()
+ {
+ var client = new RestClient("http://example.com");
+ var request = new RestRequest("api/search", Method.GET);
+ request.AddParameter("q", "test");
+ var uri = client.BuildUri(request);
+ Assert.Contains("q=test", uri.ToString());
+ }
+
+ [Fact]
+ public void BuildUri_Does_Not_Add_QueryString_For_POST()
+ {
+ var client = new RestClient("http://example.com");
+ var request = new RestRequest("api/users", Method.POST);
+ request.AddParameter("name", "test");
+ var uri = client.BuildUri(request);
+ Assert.DoesNotContain("?", uri.ToString());
+ }
+
+ [Fact]
+ public void BuildUri_With_UrlSegment_Replaces_Token()
+ {
+ var client = new RestClient("http://example.com");
+ var request = new RestRequest("users/{id}");
+ request.AddUrlSegment("id", "42");
+ var uri = client.BuildUri(request);
+ Assert.Equal("http://example.com/users/42", uri.ToString());
+ }
+
+ [Fact]
+ public void BuildUri_Strips_Leading_Slash_From_Resource()
+ {
+ var client = new RestClient("http://example.com");
+ var request = new RestRequest("/api/users");
+ var uri = client.BuildUri(request);
+ Assert.Equal("http://example.com/api/users", uri.ToString());
+ }
+
+ [Fact]
+ public void BuildUri_Multiple_QueryString_Params()
+ {
+ var client = new RestClient("http://example.com");
+ var request = new RestRequest("search", Method.GET);
+ request.AddParameter("q", "test");
+ request.AddParameter("page", "1");
+ var uri = client.BuildUri(request);
+ Assert.Contains("q=test", uri.ToString());
+ Assert.Contains("page=1", uri.ToString());
+ }
+
+ [Fact]
+ public void BuildUri_With_DELETE_Includes_QueryString()
+ {
+ var client = new RestClient("http://example.com");
+ var request = new RestRequest("items", Method.DELETE);
+ request.AddParameter("id", "5");
+ var uri = client.BuildUri(request);
+ Assert.Contains("id=5", uri.ToString());
+ }
+
+ [Fact]
+ public void BuildUri_With_HEAD_Includes_QueryString()
+ {
+ var client = new RestClient("http://example.com");
+ var request = new RestRequest("items", Method.HEAD);
+ request.AddParameter("id", "5");
+ var uri = client.BuildUri(request);
+ Assert.Contains("id=5", uri.ToString());
+ }
+
+ [Fact]
+ public void BuildUri_With_OPTIONS_Includes_QueryString()
+ {
+ var client = new RestClient("http://example.com");
+ var request = new RestRequest("items", Method.OPTIONS);
+ request.AddParameter("id", "5");
+ var uri = client.BuildUri(request);
+ Assert.Contains("id=5", uri.ToString());
+ }
+
+ [Fact]
+ public void ClientCertificates_Can_Be_Set()
+ {
+ var client = new RestClient();
+ var certs = new System.Security.Cryptography.X509Certificates.X509CertificateCollection();
+ client.ClientCertificates = certs;
+ Assert.Equal(certs, client.ClientCertificates);
+ }
+
+ [Fact]
+ public void Proxy_Can_Be_Set()
+ {
+ var client = new RestClient();
+ var proxy = new WebProxy("http://proxy.example.com:8080");
+ client.Proxy = proxy;
+ Assert.Equal(proxy, client.Proxy);
+ }
+ }
+}
diff --git a/RestSharp.Tests.Coverage/RestRequestTests.cs b/RestSharp.Tests.Coverage/RestRequestTests.cs
new file mode 100644
index 000000000..1776c4aff
--- /dev/null
+++ b/RestSharp.Tests.Coverage/RestRequestTests.cs
@@ -0,0 +1,343 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using RestSharp;
+using RestSharp.Serializers;
+using Xunit;
+
+namespace RestSharp.Tests.Coverage
+{
+ public class RestRequestTests
+ {
+ [Fact]
+ public void Default_Constructor_Sets_Method_To_GET()
+ {
+ var request = new RestRequest();
+ Assert.Equal(Method.GET, request.Method);
+ }
+
+ [Fact]
+ public void Constructor_With_Method_Sets_Method()
+ {
+ var request = new RestRequest(Method.POST);
+ Assert.Equal(Method.POST, request.Method);
+ }
+
+ [Fact]
+ public void Constructor_With_Resource_Sets_Resource()
+ {
+ var request = new RestRequest("resource/path");
+ Assert.Equal("resource/path", request.Resource);
+ }
+
+ [Fact]
+ public void Constructor_With_Resource_And_Method_Sets_Both()
+ {
+ var request = new RestRequest("resource/path", Method.PUT);
+ Assert.Equal("resource/path", request.Resource);
+ Assert.Equal(Method.PUT, request.Method);
+ }
+
+ [Fact]
+ public void Constructor_With_Uri_Sets_Resource()
+ {
+ var uri = new Uri("resource/path", UriKind.Relative);
+ var request = new RestRequest(uri);
+ Assert.Equal("resource/path", request.Resource);
+ }
+
+ [Fact]
+ public void Constructor_With_Uri_And_Method_Sets_Both()
+ {
+ var uri = new Uri("resource/path", UriKind.Relative);
+ var request = new RestRequest(uri, Method.DELETE);
+ Assert.Equal("resource/path", request.Resource);
+ Assert.Equal(Method.DELETE, request.Method);
+ }
+
+ [Fact]
+ public void Default_Request_Format_Is_Xml()
+ {
+ var request = new RestRequest();
+ Assert.Equal(DataFormat.Xml, request.RequestFormat);
+ }
+
+ [Fact]
+ public void AddParameter_String_Name_Value_Adds_GetOrPost()
+ {
+ var request = new RestRequest();
+ request.AddParameter("name", "value");
+ var param = request.Parameters.First();
+
+ Assert.Equal("name", param.Name);
+ Assert.Equal("value", param.Value);
+ Assert.Equal(ParameterType.GetOrPost, param.Type);
+ }
+
+ [Fact]
+ public void AddParameter_With_Type_Adds_Correct_Type()
+ {
+ var request = new RestRequest();
+ request.AddParameter("name", "value", ParameterType.HttpHeader);
+ var param = request.Parameters.First();
+
+ Assert.Equal(ParameterType.HttpHeader, param.Type);
+ }
+
+ [Fact]
+ public void AddParameter_Object_Adds_To_Collection()
+ {
+ var request = new RestRequest();
+ var p = new Parameter { Name = "test", Value = "val", Type = ParameterType.Cookie };
+ request.AddParameter(p);
+
+ Assert.Contains(p, request.Parameters);
+ }
+
+ [Fact]
+ public void AddHeader_Adds_HttpHeader_Parameter()
+ {
+ var request = new RestRequest();
+ request.AddHeader("Content-Type", "application/json");
+
+ var param = request.Parameters.First();
+ Assert.Equal("Content-Type", param.Name);
+ Assert.Equal("application/json", param.Value);
+ Assert.Equal(ParameterType.HttpHeader, param.Type);
+ }
+
+ [Fact]
+ public void AddCookie_Adds_Cookie_Parameter()
+ {
+ var request = new RestRequest();
+ request.AddCookie("session", "abc123");
+
+ var param = request.Parameters.First();
+ Assert.Equal("session", param.Name);
+ Assert.Equal("abc123", param.Value);
+ Assert.Equal(ParameterType.Cookie, param.Type);
+ }
+
+ [Fact]
+ public void AddUrlSegment_Adds_UrlSegment_Parameter()
+ {
+ var request = new RestRequest("users/{id}");
+ request.AddUrlSegment("id", "42");
+
+ var param = request.Parameters.First();
+ Assert.Equal("id", param.Name);
+ Assert.Equal("42", param.Value);
+ Assert.Equal(ParameterType.UrlSegment, param.Type);
+ }
+
+ [Fact]
+ public void AddBody_Json_Adds_RequestBody_Parameter()
+ {
+ var request = new RestRequest();
+ request.RequestFormat = DataFormat.Json;
+ request.AddBody(new { Name = "test", Value = 42 });
+
+ var body = request.Parameters.FirstOrDefault(p => p.Type == ParameterType.RequestBody);
+ Assert.NotNull(body);
+ Assert.Contains("test", body.Value.ToString());
+ }
+
+ [Fact]
+ public void AddBody_Xml_Adds_RequestBody_Parameter()
+ {
+ var request = new RestRequest();
+ request.RequestFormat = DataFormat.Xml;
+ request.AddBody(new TestObj { Name = "test" });
+
+ var body = request.Parameters.FirstOrDefault(p => p.Type == ParameterType.RequestBody);
+ Assert.NotNull(body);
+ Assert.Contains("test", body.Value.ToString());
+ }
+
+ [Fact]
+ public void AddBody_With_Namespace_Sets_Xml_Namespace()
+ {
+ var request = new RestRequest();
+ request.RequestFormat = DataFormat.Xml;
+ request.AddBody(new TestObj { Name = "test" }, "http://example.com/ns");
+
+ var body = request.Parameters.FirstOrDefault(p => p.Type == ParameterType.RequestBody);
+ Assert.NotNull(body);
+ }
+
+ [Fact]
+ public void AddObject_Adds_Public_Properties_As_Parameters()
+ {
+ var request = new RestRequest();
+ var obj = new { Name = "John", Age = 30 };
+ request.AddObject(obj);
+
+ Assert.Equal(2, request.Parameters.Count);
+ Assert.Equal("Name", request.Parameters[0].Name);
+ Assert.Equal("John", request.Parameters[0].Value);
+ Assert.Equal("Age", request.Parameters[1].Name);
+ Assert.Equal(30, request.Parameters[1].Value);
+ }
+
+ [Fact]
+ public void AddObject_With_Whitelist_Only_Adds_Listed_Properties()
+ {
+ var request = new RestRequest();
+ var obj = new TestObj { Name = "John", Value = 30 };
+ request.AddObject(obj, "Name");
+
+ Assert.Single(request.Parameters);
+ Assert.Equal("Name", request.Parameters[0].Name);
+ }
+
+ [Fact]
+ public void AddObject_Skips_Null_Values()
+ {
+ var request = new RestRequest();
+ var obj = new TestObj { Name = null, Value = 42 };
+ request.AddObject(obj);
+
+ Assert.DoesNotContain(request.Parameters, p => p.Name == "Name");
+ Assert.Contains(request.Parameters, p => p.Name == "Value");
+ }
+
+ [Fact]
+ public void AddFile_From_Bytes_Adds_To_Files_Collection()
+ {
+ var request = new RestRequest();
+ request.AddFile("file", new byte[] { 1, 2, 3 }, "test.txt");
+
+ Assert.Single(request.Files);
+ Assert.Equal("file", request.Files[0].Name);
+ Assert.Equal("test.txt", request.Files[0].FileName);
+ }
+
+ [Fact]
+ public void AddFile_From_Bytes_With_ContentType_Sets_ContentType()
+ {
+ var request = new RestRequest();
+ request.AddFile("file", new byte[] { 1, 2, 3 }, "test.txt", "text/plain");
+
+ Assert.Equal("text/plain", request.Files[0].ContentType);
+ }
+
+ [Fact]
+ public void IncreaseNumAttempts_Increments_Attempts()
+ {
+ var request = new RestRequest();
+ Assert.Equal(0, request.Attempts);
+
+ request.IncreaseNumAttempts();
+ Assert.Equal(1, request.Attempts);
+
+ request.IncreaseNumAttempts();
+ Assert.Equal(2, request.Attempts);
+ }
+
+ [Fact]
+ public void Request_Has_Empty_Parameters_By_Default()
+ {
+ var request = new RestRequest();
+ Assert.NotNull(request.Parameters);
+ Assert.Empty(request.Parameters);
+ }
+
+ [Fact]
+ public void Request_Has_Empty_Files_By_Default()
+ {
+ var request = new RestRequest();
+ Assert.NotNull(request.Files);
+ Assert.Empty(request.Files);
+ }
+
+ [Fact]
+ public void OnBeforeDeserialization_Can_Be_Set_And_Invoked()
+ {
+ var request = new RestRequest();
+ bool callbackInvoked = false;
+ request.OnBeforeDeserialization = r => { callbackInvoked = true; };
+
+ var response = new RestResponse { Content = "test" };
+ request.OnBeforeDeserialization(response);
+
+ Assert.True(callbackInvoked);
+ }
+
+ [Fact]
+ public void Request_Timeout_Can_Be_Set()
+ {
+ var request = new RestRequest();
+ request.Timeout = 5000;
+ Assert.Equal(5000, request.Timeout);
+ }
+
+ [Fact]
+ public void Request_DateFormat_Can_Be_Set()
+ {
+ var request = new RestRequest();
+ request.DateFormat = "yyyy-MM-dd";
+ Assert.Equal("yyyy-MM-dd", request.DateFormat);
+ }
+
+ [Fact]
+ public void Request_XmlNamespace_Can_Be_Set()
+ {
+ var request = new RestRequest();
+ request.XmlNamespace = "http://example.com";
+ Assert.Equal("http://example.com", request.XmlNamespace);
+ }
+
+ [Fact]
+ public void Request_RootElement_Can_Be_Set()
+ {
+ var request = new RestRequest();
+ request.RootElement = "data";
+ Assert.Equal("data", request.RootElement);
+ }
+
+ [Fact]
+ public void Request_Credentials_Can_Be_Set()
+ {
+ var request = new RestRequest();
+ var creds = new System.Net.NetworkCredential("user", "pass");
+ request.Credentials = creds;
+ Assert.Equal(creds, request.Credentials);
+ }
+
+ [Fact]
+ public void Request_JsonSerializer_Has_Default()
+ {
+ var request = new RestRequest();
+ Assert.NotNull(request.JsonSerializer);
+ }
+
+ [Fact]
+ public void Request_XmlSerializer_Has_Default()
+ {
+ var request = new RestRequest();
+ Assert.NotNull(request.XmlSerializer);
+ }
+
+ [Fact]
+ public void AddObject_With_Array_Property_Joins_Values()
+ {
+ var request = new RestRequest();
+ var obj = new ObjectWithArray { Tags = new[] { "a", "b", "c" } };
+ request.AddObject(obj);
+
+ var param = request.Parameters.First(p => p.Name == "Tags");
+ Assert.Equal("a,b,c", param.Value);
+ }
+
+ private class TestObj
+ {
+ public string Name { get; set; }
+ public int Value { get; set; }
+ }
+
+ private class ObjectWithArray
+ {
+ public string[] Tags { get; set; }
+ }
+ }
+}
diff --git a/RestSharp.Tests.Coverage/RestSharp.Tests.Coverage.csproj b/RestSharp.Tests.Coverage/RestSharp.Tests.Coverage.csproj
new file mode 100644
index 000000000..01733cd61
--- /dev/null
+++ b/RestSharp.Tests.Coverage/RestSharp.Tests.Coverage.csproj
@@ -0,0 +1,37 @@
+
+
+
+ net7.0
+ disable
+ disable
+ FRAMEWORK
+ CS0618;CS0672;CS0162;CS0168;CS0219;CS8600;CS8601;CS8602;CS8603;CS8604;CS8625;CS0108;CS0114;CS0579;CS0436;CS8981
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/RestSharp.Tests.Coverage/SerializerCoverageTests.cs b/RestSharp.Tests.Coverage/SerializerCoverageTests.cs
new file mode 100644
index 000000000..5692a1d44
--- /dev/null
+++ b/RestSharp.Tests.Coverage/SerializerCoverageTests.cs
@@ -0,0 +1,475 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using RestSharp.Serializers;
+using Xunit;
+
+namespace RestSharp.Tests.Coverage
+{
+ public class JsonSerializerTests
+ {
+ [Fact]
+ public void Serialize_Simple_Object()
+ {
+ var serializer = new JsonSerializer();
+ var result = serializer.Serialize(new { Name = "test", Value = 42 });
+ Assert.Contains("test", result);
+ Assert.Contains("42", result);
+ }
+
+ [Fact]
+ public void ContentType_Defaults_To_ApplicationJson()
+ {
+ var serializer = new JsonSerializer();
+ Assert.Equal("application/json", serializer.ContentType);
+ }
+
+ [Fact]
+ public void ContentType_Can_Be_Set()
+ {
+ var serializer = new JsonSerializer();
+ serializer.ContentType = "text/json";
+ Assert.Equal("text/json", serializer.ContentType);
+ }
+
+ [Fact]
+ public void Serialize_List_Object()
+ {
+ var serializer = new JsonSerializer();
+ var result = serializer.Serialize(new List { "a", "b", "c" });
+ Assert.Contains("a", result);
+ Assert.Contains("b", result);
+ }
+
+ [Fact]
+ public void Serialize_Null_Returns_Null_Json()
+ {
+ var serializer = new JsonSerializer();
+ var result = serializer.Serialize(null);
+ Assert.Equal("null", result);
+ }
+
+ [Fact]
+ public void Serialize_Complex_Object()
+ {
+ var serializer = new JsonSerializer();
+ var obj = new SerializableObj
+ {
+ Name = "Foo",
+ Age = 25,
+ Items = new List { "x", "y" }
+ };
+ var result = serializer.Serialize(obj);
+ Assert.Contains("Foo", result);
+ Assert.Contains("25", result);
+ }
+
+ [Fact]
+ public void RootElement_Can_Be_Set()
+ {
+ var serializer = new JsonSerializer();
+ serializer.RootElement = "data";
+ Assert.Equal("data", serializer.RootElement);
+ }
+
+ [Fact]
+ public void Namespace_Can_Be_Set()
+ {
+ var serializer = new JsonSerializer();
+ serializer.Namespace = "ns";
+ Assert.Equal("ns", serializer.Namespace);
+ }
+
+ [Fact]
+ public void DateFormat_Can_Be_Set()
+ {
+ var serializer = new JsonSerializer();
+ serializer.DateFormat = "yyyy-MM-dd";
+ Assert.Equal("yyyy-MM-dd", serializer.DateFormat);
+ }
+ }
+
+ public class XmlSerializerCoverageTests
+ {
+ [Fact]
+ public void Default_ContentType_Is_ApplicationXml()
+ {
+ var serializer = new XmlSerializer();
+ Assert.Equal("text/xml", serializer.ContentType);
+ }
+
+ [Fact]
+ public void Serialize_Simple_Object()
+ {
+ var serializer = new XmlSerializer();
+ var result = serializer.Serialize(new SimpleXmlObj { Name = "test", Value = 42 });
+ Assert.Contains("test", result);
+ Assert.Contains("42", result);
+ }
+
+ [Fact]
+ public void RootElement_Override()
+ {
+ var serializer = new XmlSerializer();
+ serializer.RootElement = "CustomRoot";
+ var result = serializer.Serialize(new SimpleXmlObj { Name = "test" });
+ Assert.Contains("CustomRoot", result);
+ }
+
+ [Fact]
+ public void Namespace_Is_Applied()
+ {
+ var serializer = new XmlSerializer();
+ serializer.Namespace = "http://example.com/ns";
+ var result = serializer.Serialize(new SimpleXmlObj { Name = "test" });
+ Assert.Contains("http://example.com/ns", result);
+ }
+
+ [Fact]
+ public void Serialize_With_Nullable_Property()
+ {
+ var serializer = new XmlSerializer();
+ var result = serializer.Serialize(new ObjWithNullable { Value = null, Name = "test" });
+ Assert.Contains("test", result);
+ }
+
+ [Fact]
+ public void Serialize_With_Nullable_Property_Set()
+ {
+ var serializer = new XmlSerializer();
+ var result = serializer.Serialize(new ObjWithNullable { Value = 42, Name = "test" });
+ Assert.Contains("42", result);
+ }
+
+ [Fact]
+ public void Serialize_With_DateTime()
+ {
+ var serializer = new XmlSerializer();
+ var result = serializer.Serialize(new ObjWithDate { Date = new DateTime(2023, 6, 15) });
+ Assert.Contains("2023", result);
+ }
+
+ [Fact]
+ public void Serialize_With_DateFormat()
+ {
+ var serializer = new XmlSerializer();
+ serializer.DateFormat = "yyyy-MM-dd";
+ var result = serializer.Serialize(new ObjWithDate { Date = new DateTime(2023, 6, 15) });
+ Assert.Contains("2023-06-15", result);
+ }
+
+ [Fact]
+ public void Serialize_With_Enum()
+ {
+ var serializer = new XmlSerializer();
+ var result = serializer.Serialize(new ObjWithEnum { Status = Method.POST });
+ Assert.Contains("POST", result);
+ }
+
+ [Fact]
+ public void Serialize_With_Guid()
+ {
+ var serializer = new XmlSerializer();
+ var guid = Guid.NewGuid();
+ var result = serializer.Serialize(new ObjWithGuid { Id = guid });
+ Assert.Contains(guid.ToString(), result);
+ }
+
+ [Fact]
+ public void Serialize_With_Boolean()
+ {
+ var serializer = new XmlSerializer();
+ var result = serializer.Serialize(new ObjWithBool { Active = true, Disabled = false });
+ Assert.Contains("true", result.ToLower());
+ Assert.Contains("false", result.ToLower());
+ }
+
+ [Fact]
+ public void Serialize_With_List()
+ {
+ var serializer = new XmlSerializer();
+ var obj = new ObjWithList
+ {
+ Name = "parent",
+ Items = new List
+ {
+ new SimpleXmlObj { Name = "child1", Value = 1 },
+ new SimpleXmlObj { Name = "child2", Value = 2 }
+ }
+ };
+ var result = serializer.Serialize(obj);
+ Assert.Contains("child1", result);
+ Assert.Contains("child2", result);
+ }
+
+ [Fact]
+ public void Serialize_With_Decimal()
+ {
+ var serializer = new XmlSerializer();
+ var result = serializer.Serialize(new ObjWithDecimal { Price = 19.95m });
+ Assert.Contains("19.95", result);
+ }
+
+ [Fact]
+ public void Serialize_With_Double()
+ {
+ var serializer = new XmlSerializer();
+ var result = serializer.Serialize(new ObjWithDouble { Rate = 3.14 });
+ Assert.Contains("3.14", result);
+ }
+
+ [Fact]
+ public void Serialize_With_Long()
+ {
+ var serializer = new XmlSerializer();
+ var result = serializer.Serialize(new ObjWithLong { BigNum = long.MaxValue });
+ Assert.Contains(long.MaxValue.ToString(), result);
+ }
+
+ [Fact]
+ public void Serialize_With_TimeSpan()
+ {
+ var serializer = new XmlSerializer();
+ var result = serializer.Serialize(new ObjWithTimeSpan { Duration = TimeSpan.FromHours(1) });
+ Assert.NotNull(result);
+ }
+
+ [Fact]
+ public void ContentType_Can_Be_Set()
+ {
+ var serializer = new XmlSerializer();
+ serializer.ContentType = "application/xml";
+ Assert.Equal("application/xml", serializer.ContentType);
+ }
+ }
+
+ public class DotNetXmlSerializerTests
+ {
+ [Fact]
+ public void Default_ContentType_Is_ApplicationXml()
+ {
+ var serializer = new DotNetXmlSerializer();
+ Assert.Equal("application/xml", serializer.ContentType);
+ }
+
+ [Fact]
+ public void Constructor_With_Namespace()
+ {
+ var serializer = new DotNetXmlSerializer("http://example.com");
+ Assert.Equal("http://example.com", serializer.Namespace);
+ }
+
+ [Fact]
+ public void Serialize_Simple_Object()
+ {
+ var serializer = new DotNetXmlSerializer();
+ var result = serializer.Serialize(new SimpleXmlObj { Name = "test", Value = 42 });
+ Assert.Contains("test", result);
+ Assert.Contains("42", result);
+ }
+
+ [Fact]
+ public void Encoding_Defaults_To_UTF8()
+ {
+ var serializer = new DotNetXmlSerializer();
+ Assert.Equal(System.Text.Encoding.UTF8, serializer.Encoding);
+ }
+
+ [Fact]
+ public void Properties_Can_Be_Set()
+ {
+ var serializer = new DotNetXmlSerializer();
+ serializer.RootElement = "Root";
+ serializer.DateFormat = "yyyy-MM-dd";
+ serializer.ContentType = "text/xml";
+
+ Assert.Equal("Root", serializer.RootElement);
+ Assert.Equal("yyyy-MM-dd", serializer.DateFormat);
+ Assert.Equal("text/xml", serializer.ContentType);
+ }
+ }
+
+ public class DotNetXmlDeserializerTests
+ {
+ [Fact]
+ public void Deserialize_Simple_Object()
+ {
+ var deserializer = new RestSharp.Deserializers.DotNetXmlDeserializer();
+ var xml = "test42";
+ var response = new RestResponse { Content = xml };
+ var result = deserializer.Deserialize(response);
+
+ Assert.Equal("test", result.Name);
+ Assert.Equal(42, result.Value);
+ }
+
+ [Fact]
+ public void Deserialize_Empty_Content_Returns_Default()
+ {
+ var deserializer = new RestSharp.Deserializers.DotNetXmlDeserializer();
+ var response = new RestResponse { Content = "" };
+ var result = deserializer.Deserialize(response);
+
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void Deserialize_Null_Content_Returns_Default()
+ {
+ var deserializer = new RestSharp.Deserializers.DotNetXmlDeserializer();
+ var response = new RestResponse { Content = null };
+ var result = deserializer.Deserialize(response);
+
+ Assert.Null(result);
+ }
+
+ [Fact]
+ public void Properties_Can_Be_Set()
+ {
+ var deserializer = new RestSharp.Deserializers.DotNetXmlDeserializer();
+ deserializer.DateFormat = "yyyy-MM-dd";
+ deserializer.Namespace = "http://example.com";
+ deserializer.RootElement = "data";
+
+ Assert.Equal("yyyy-MM-dd", deserializer.DateFormat);
+ Assert.Equal("http://example.com", deserializer.Namespace);
+ Assert.Equal("data", deserializer.RootElement);
+ }
+ }
+
+ public class SerializeAsAttributeTests
+ {
+ [Fact]
+ public void Default_NameStyle_Is_AsIs()
+ {
+ var attr = new SerializeAsAttribute();
+ Assert.Equal(NameStyle.AsIs, attr.NameStyle);
+ }
+
+ [Fact]
+ public void Default_Index_Is_MaxValue()
+ {
+ var attr = new SerializeAsAttribute();
+ Assert.Equal(int.MaxValue, attr.Index);
+ }
+
+ [Fact]
+ public void TransformName_AsIs_Returns_Input()
+ {
+ var attr = new SerializeAsAttribute();
+ Assert.Equal("TestName", attr.TransformName("TestName"));
+ }
+
+ [Fact]
+ public void TransformName_CamelCase_Transforms()
+ {
+ var attr = new SerializeAsAttribute { NameStyle = NameStyle.CamelCase };
+ var result = attr.TransformName("TestName");
+ Assert.Equal("testName", result);
+ }
+
+ [Fact]
+ public void TransformName_PascalCase_Transforms()
+ {
+ var attr = new SerializeAsAttribute { NameStyle = NameStyle.PascalCase };
+ var result = attr.TransformName("test_name");
+ Assert.Equal("TestName", result);
+ }
+
+ [Fact]
+ public void TransformName_LowerCase_Transforms()
+ {
+ var attr = new SerializeAsAttribute { NameStyle = NameStyle.LowerCase };
+ var result = attr.TransformName("TestName");
+ Assert.Equal("testname", result);
+ }
+
+ [Fact]
+ public void TransformName_With_Custom_Name()
+ {
+ var attr = new SerializeAsAttribute { Name = "custom", NameStyle = NameStyle.LowerCase };
+ var result = attr.TransformName("OriginalName");
+ Assert.Equal("custom", result);
+ }
+
+ [Fact]
+ public void Attribute_Property_Can_Be_Set()
+ {
+ var attr = new SerializeAsAttribute { Attribute = true };
+ Assert.True(attr.Attribute);
+ }
+
+ [Fact]
+ public void Culture_Defaults_To_InvariantCulture()
+ {
+ var attr = new SerializeAsAttribute();
+ Assert.Equal(CultureInfo.InvariantCulture, attr.Culture);
+ }
+ }
+
+ public class SimpleXmlObj
+ {
+ public string Name { get; set; }
+ public int Value { get; set; }
+ }
+
+ public class ObjWithNullable
+ {
+ public string Name { get; set; }
+ public int? Value { get; set; }
+ }
+
+ public class ObjWithDate
+ {
+ public DateTime Date { get; set; }
+ }
+
+ public class ObjWithEnum
+ {
+ public Method Status { get; set; }
+ }
+
+ public class ObjWithGuid
+ {
+ public Guid Id { get; set; }
+ }
+
+ public class ObjWithBool
+ {
+ public bool Active { get; set; }
+ public bool Disabled { get; set; }
+ }
+
+ public class ObjWithList
+ {
+ public string Name { get; set; }
+ public List Items { get; set; }
+ }
+
+ public class ObjWithDecimal
+ {
+ public decimal Price { get; set; }
+ }
+
+ public class ObjWithDouble
+ {
+ public double Rate { get; set; }
+ }
+
+ public class ObjWithLong
+ {
+ public long BigNum { get; set; }
+ }
+
+ public class ObjWithTimeSpan
+ {
+ public TimeSpan Duration { get; set; }
+ }
+
+ public class SerializableObj
+ {
+ public string Name { get; set; }
+ public int Age { get; set; }
+ public List Items { get; set; }
+ }
+}
diff --git a/RestSharp.Tests.Coverage/SmokeTest.cs b/RestSharp.Tests.Coverage/SmokeTest.cs
new file mode 100644
index 000000000..0094dd4a3
--- /dev/null
+++ b/RestSharp.Tests.Coverage/SmokeTest.cs
@@ -0,0 +1,14 @@
+using Xunit;
+
+namespace RestSharp.Tests.Coverage
+{
+ public class SmokeTest
+ {
+ [Fact]
+ public void Smoke_RestClient_Can_Be_Created()
+ {
+ var client = new RestClient("http://example.com");
+ Assert.Equal("http://example.com", client.BaseUrl);
+ }
+ }
+}
diff --git a/RestSharp.Tests.Coverage/ValidationTests.cs b/RestSharp.Tests.Coverage/ValidationTests.cs
new file mode 100644
index 000000000..9aaa11468
--- /dev/null
+++ b/RestSharp.Tests.Coverage/ValidationTests.cs
@@ -0,0 +1,85 @@
+using System;
+using RestSharp.Validation;
+using Xunit;
+
+namespace RestSharp.Tests.Coverage
+{
+ public class ValidateTests
+ {
+ [Fact]
+ public void IsBetween_Does_Not_Throw_For_Valid_Value()
+ {
+ Validate.IsBetween(5, 1, 10);
+ }
+
+ [Fact]
+ public void IsBetween_At_Min_Boundary_Does_Not_Throw()
+ {
+ Validate.IsBetween(1, 1, 10);
+ }
+
+ [Fact]
+ public void IsBetween_At_Max_Boundary_Does_Not_Throw()
+ {
+ Validate.IsBetween(10, 1, 10);
+ }
+
+ [Fact]
+ public void IsBetween_Below_Min_Throws()
+ {
+ Assert.Throws(() => Validate.IsBetween(0, 1, 10));
+ }
+
+ [Fact]
+ public void IsBetween_Above_Max_Throws()
+ {
+ Assert.Throws(() => Validate.IsBetween(11, 1, 10));
+ }
+
+ [Fact]
+ public void IsValidLength_Does_Not_Throw_For_Valid_String()
+ {
+ Validate.IsValidLength("hello", 10);
+ }
+
+ [Fact]
+ public void IsValidLength_At_Max_Does_Not_Throw()
+ {
+ Validate.IsValidLength("hello", 5);
+ }
+
+ [Fact]
+ public void IsValidLength_Over_Max_Throws()
+ {
+ Assert.Throws(() => Validate.IsValidLength("hello world", 5));
+ }
+
+ [Fact]
+ public void IsValidLength_Null_Does_Not_Throw()
+ {
+ Validate.IsValidLength(null, 5);
+ }
+ }
+
+ public class RequireTests
+ {
+ [Fact]
+ public void Argument_Does_Not_Throw_For_NonNull()
+ {
+ Require.Argument("param", "value");
+ }
+
+ [Fact]
+ public void Argument_Throws_For_Null()
+ {
+ Assert.Throws(() => Require.Argument("param", null));
+ }
+
+ [Fact]
+ public void Argument_Throws_With_Correct_ParamName()
+ {
+ var ex = Assert.Throws(() => Require.Argument("myParam", null));
+ Assert.Contains("myParam", ex.ParamName);
+ }
+ }
+}