Commit 1328e773 authored by Brickner_cp's avatar Brickner_cp

GRE

Overload UInt48.Parse()
Code Coverage 97.68%
parent 6f0f18cd
......@@ -56,12 +56,72 @@ namespace PcapDotNet.Base.Test
for (int i = 0; i != 100; ++i)
{
UInt48 expected = (UInt48)random.NextLong(UInt48.MaxValue + 1);
UInt48 actual = UInt48.Parse(expected.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture);
Assert.AreEqual(expected, actual);
actual = UInt48.Parse(expected.ToString(), NumberStyles.Integer);
Assert.AreEqual(expected, actual);
actual = UInt48.Parse(expected.ToString(), CultureInfo.InvariantCulture);
Assert.AreEqual(expected, actual);
actual = UInt48.Parse(expected.ToString());
Assert.AreEqual(expected, actual);
}
}
[TestMethod]
[ExpectedException(typeof(OverflowException))]
public void ParseTooBigTest()
{
UInt48 value = UInt48.Parse(ulong.MaxValue.ToString());
Assert.IsNotNull(value);
}
[TestMethod]
[ExpectedException(typeof(OverflowException))]
public void ParseTooBigTestEvenForUInt64()
{
UInt48 value = UInt48.Parse(ulong.MaxValue + "0");
Assert.IsNotNull(value);
}
// [TestMethod]
// public void UInt48Test()
// {
// UInt48 value = (UInt48)0x010203040506;
// byte[] buffer = new byte[UInt48.SizeOf];
//
// buffer.Write(0, value, Endianity.Big);
// Assert.AreEqual(value, buffer.ReadUInt48(0, Endianity.Big));
// Assert.AreEqual(0x01, buffer[0]);
// Assert.AreEqual(0x02, buffer[1]);
// Assert.AreEqual(0x03, buffer[2]);
// Assert.AreEqual(0x04, buffer[3]);
// Assert.AreEqual(0x05, buffer[4]);
// Assert.AreEqual(0x06, buffer[5]);
//
// int offset = 0;
// buffer.Write(ref offset, value, Endianity.Big);
// Assert.AreEqual(value, buffer.ReadUInt48(0, Endianity.Big));
// Assert.AreEqual(6, offset);
//
// buffer.Write(0, value, Endianity.Small);
// Assert.AreEqual(value, buffer.ReadUInt48(0, Endianity.Small));
// Assert.AreEqual(0x06, buffer[0]);
// Assert.AreEqual(0x05, buffer[1]);
// Assert.AreEqual(0x04, buffer[2]);
// Assert.AreEqual(0x03, buffer[3]);
// Assert.AreEqual(0x02, buffer[4]);
// Assert.AreEqual(0x01, buffer[5]);
//
// offset = 0;
// buffer.Write(ref offset, value, Endianity.Small);
// Assert.AreEqual(value, buffer.ReadUInt48(0, Endianity.Small));
// Assert.AreEqual(6, offset);
// }
[TestMethod]
public void UInt48Test()
{
......@@ -71,6 +131,7 @@ namespace PcapDotNet.Base.Test
UInt48 value = random.NextUInt48();
Assert.AreEqual(value, value);
Assert.AreNotEqual(value, "1");
Assert.IsTrue(value == value);
Assert.IsFalse(value != value);
Assert.IsNotNull(value.GetHashCode());
......
......@@ -15,26 +15,389 @@ namespace PcapDotNet.Base
/// </summary>
public const int SizeOf = 6;
/// <summary>
/// The minimum value of this type.
/// </summary>
public static readonly UInt48 MinValue = 0;
/// <summary>
/// The maximum value of this type.
/// </summary>
public static readonly UInt48 MaxValue = (UInt48)0x0000FFFFFFFFFFFF;
/// <summary>
/// Converts the string representation of a number in a specified style to its 48-bit unsigned integer equivalent.
/// Converts the string representation of a number to its 48-bit unsigned integer equivalent.
/// </summary>
/// <param name="value">A string that represents the number to convert.</param>
/// <returns>A 48-bit unsigned integer equivalent to the number contained in <paramref name="value"/>.</returns>
/// <exception cref="ArgumentNullException">The <paramref name="value"/> parameter is <see langword="null"/>.</exception>
/// <exception cref="FormatException">The <paramref name="value"/> parameter is not in the correct format.</exception>
/// <exception cref="OverflowException">The <paramref name="value"/> parameter represents a number less than <see cref="UInt48.MinValue"/> or greater than <see cref="UInt48.MaxValue"/>.</exception>
/// <remarks>
/// The <paramref name="value"/> parameter should be the string representation of a number in the following form.
/// <para>[ws][sign]digits[ws]</para>
/// <para> Elements in square brackets ([ and ]) are optional. The following table describes each element.</para>
/// <list type="table">
/// <listheader>
/// <term>Element</term>
/// <description>Description</description>
/// </listheader>
/// <item><term>ws</term><description>Optional white space.</description></item>
/// <item>
/// <term>sign</term>
/// <description>
/// An optional sign.
/// Valid sign characters are determined by the <see cref="NumberFormatInfo.NegativeSign"/> and <see cref="NumberFormatInfo.PositiveSign"/> properties of the current culture.
/// However, the negative sign symbol can be used only with zero; otherwise, the method throws an <see cref="OverflowException"/>.
/// </description>
/// </item>
/// <item><term>digits</term><description>A sequence of digits ranging from 0 to 9. Any leading zeros are ignored.</description></item>
/// </list>
/// <note>
/// The string specified by the <paramref name="value"/> parameter is interpreted by using the <see cref="NumberStyles.Integer"/> style.
/// It cannot contain any group separators or decimal separator, and it cannot have a decimal portion.
/// </note>
/// The <paramref name="value"/> parameter is parsed by using the formatting information in a <see cref="NumberFormatInfo"/> object that is initialized for the current system culture.
/// For more information, see <see cref="NumberFormatInfo.CurrentInfo"/>.
/// To parse a string by using the formatting information of a specific culture, use the <see cref="Parse(String, IFormatProvider)"/> method.
/// </remarks>
public static UInt48 Parse(string value)
{
return Parse(value, NumberStyles.Integer, CultureInfo.CurrentCulture);
}
/// <summary>
/// Converts the string representation of a number in a specified culture-specific format to its 64-bit unsigned integer equivalent.
/// </summary>
/// <param name="value">A string that represents the number to convert.</param>
/// <param name="provider">An object that supplies culture-specific formatting information about <paramref name="value"/>.</param>
/// <returns>A 48-bit unsigned integer equivalent to the number specified in <paramref name="value"/>.</returns>
/// <exception cref="ArgumentNullException">The <paramref name="value"/> parameter is <see langword="null"/>.</exception>
/// <exception cref="FormatException">The <paramref name="value"/> parameter is not in the correct style.</exception>
/// <exception cref="OverflowException">
/// The <paramref name="value"/> parameter represents a number less than <see cref="UInt48.MinValue"/> or greater than <see cref="UInt48.MaxValue"/>.
/// </exception>
/// <remarks>
/// This overload of the Parse(String, IFormatProvider) method is typically used to convert text that can be formatted in a variety of ways to a <see cref="UInt48"/> value.
/// For example, it can be used to convert the text entered by a user into an HTML text box to a numeric value.
/// <para>The <paramref name="value"/> parameter contains a number of the form:</para>
/// <para>[ws][sign]digits[ws]</para>
/// <para>
/// Items in square brackets ([ and ]) are optional.
/// The following table describes each element.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Element</term>
/// <description>Description</description>
/// </listheader>
/// <item><term>ws</term><description>Optional white space.</description></item>
/// <item>
/// <term>sign</term>
/// <description>An optional positive sign, or a negative sign if <paramref name="value"/> represents the value zero.</description>
/// </item>
/// <item><term>digits</term><description>A sequence of digits from 0 through 9.</description></item>
/// </list>
/// The <paramref name="value"/> parameter is interpreted using the <see cref="NumberStyles.Integer"/> style.
/// In addition to the unsigned integer value's decimal digits, only leading and trailing spaces along with a leading sign is allowed.
/// (If the negative sign is present, <paramref name="value"/> must represent a value of zero, or the method throws an <see cref="OverflowException"/>.)
/// To explicitly define the style elements together with the culture-specific formatting information that can be present in <paramref name="value"/>, use the <see cref="Parse(String, NumberStyles, IFormatProvider)"/> method.
/// <para>
/// The <paramref name="provider"/> parameter is an <see cref="IFormatProvider"/> implementation whose <see cref="IFormatProvider.GetFormat"/> method returns a <see cref="NumberFormatInfo"/> object that provides culture-specific information about the format of <paramref name="value"/>.
/// There are three ways to use the <paramref name="provider"/> parameter to supply custom formatting information to the parse operation:
/// </para>
/// <list type="bullet">
/// <item>You can pass the actual <see cref="NumberFormatInfo"/> object that provides formatting information. (Its implementation of <see cref="IFormatProvider.GetFormat"/> simply returns itself.)</item>
/// <item>You can pass a <see cref="CultureInfo"/> object that specifies the culture whose formatting is to be used. Its <see cref="CultureInfo.NumberFormat"/> property provides formatting information.</item>
/// <item>You can pass a custom <see cref="IFormatProvider"/> implementation. Its <see cref="IFormatProvider.GetFormat"/> method must instantiate and return the <see cref="NumberFormatInfo"/> object that provides formatting information.</item>
/// </list>
/// If provider is <see langword="null"/>, the <see cref="NumberFormatInfo"/> object for the current culture is used.
/// </remarks>
public static UInt48 Parse(string value, IFormatProvider provider)
{
return Parse(value, NumberStyles.Integer, provider);
}
/// <summary>
/// Converts the string representation of a number in a specified style to its 64-bit unsigned integer equivalent.
/// </summary>
/// <param name="value">A string representing the number to convert.</param>
/// <param name="value">
/// A string that represents the number to convert.
/// The string is interpreted by using the style specified by the <paramref name="style"/> parameter.
/// </param>
/// <param name="style">
/// A bitwise combination of the enumeration values that specifies the permitted format of <paramref name="value"/>.
/// A typical value to specify is <see cref="NumberStyles.Integer"/>.
/// </param>
/// <returns>A 48-bit unsigned integer equivalent to the number specified in <paramref name="value"/>.</returns>
/// <exception cref="ArgumentNullException">The <paramref name="value"/> parameter is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException">
/// <paramref name="style"/> is not a <see cref="NumberStyles"/> value.
/// <para>-or-</para>
/// <para><paramref name="style"/> is not a combination of <see cref="NumberStyles.AllowHexSpecifier"/> and <see cref="NumberStyles.HexNumber"/> values.</para>
/// </exception>
/// <exception cref="FormatException">The <paramref name="value"/> parameter is not in a format compliant with <paramref name="style"/>.</exception>
/// <exception cref="OverflowException">
/// The <paramref name="value"/> parameter represents a number less than <see cref="UInt48.MinValue"/> or greater than <see cref="UInt48.MaxValue"/>.
/// <para>-or-</para>
/// <para><paramref name="value"/> includes non-zero, fractional digits.</para>
/// </exception>
/// <remarks>
/// The <paramref name="style"/> parameter defines the style elements (such as white space, the positive or negative sign symbol, the group separator symbol, or the decimal point symbol) that are allowed in the s parameter for the parse operation to succeed.
/// It must be a combination of bit flags from the <see cref="NumberStyles"/> enumeration.
/// <para>Depending on the value of style, the <paramref name="value"/> parameter may include the following elements:</para>
/// <para>[ws][$][sign][digits,]digits[.fractional_digits][E[sign]exponential_digits][ws]</para>
/// <para>
/// Elements in square brackets ([ and ]) are optional.
/// If <paramref name="style"/> includes <see cref="NumberStyles.AllowHexSpecifier"/>, the <paramref name="value"/> parameter may contain the following elements:
/// </para>
/// <para>[ws]hexdigits[ws]</para>
/// <para>The following table describes each element.</para>
/// <list type="table">
/// <listheader>
/// <term>Element</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>ws</term>
/// <description>
/// Optional white space.
/// White space can appear at the start of <paramref name="value"/> if <paramref name="style"/> includes the <see cref="NumberStyles.AllowLeadingWhite"/> flag,
/// and it can appear at the end of <paramref name="style"/> if <paramref name="style"/> includes the <see cref="NumberStyles.AllowTrailingWhite"/> flag.
/// </description>
/// </item>
/// <item>
/// <term>$</term>
/// <description>
/// A culture-specific currency symbol.
/// Its position in the string is defined by the <see cref="NumberFormatInfo.CurrencyNegativePattern"/> and <see cref="NumberFormatInfo.CurrencyPositivePattern"/> properties of the current culture.
/// The current culture's currency symbol can appear in <paramref name="value"/> if <paramref name="style"/> includes the <see cref="NumberStyles.AllowCurrencySymbol"/> flag.
/// </description>
/// </item>
/// <item>
/// <term>sign</term>
/// <description>
/// An optional sign.
/// The sign can appear at the start of <paramref name="value"/> if <paramref name="style"/> includes the <see cref="NumberStyles.AllowLeadingSign"/> flag, and it can appear at the end of <paramref name="value"/> if <paramref name="style"/> includes the <see cref="NumberStyles.AllowTrailingSign"/> flag.
/// Parentheses can be used in <paramref name="value"/> to indicate a negative value if <paramref name="style"/> includes the <see cref="NumberStyles.AllowParentheses"/> flag.
/// However, the negative sign symbol can be used only with zero; otherwise, the method throws an <see cref="OverflowException"/>.
/// </description>
/// </item>
/// <item>
/// <term>digits<para>fractional_digits</para><para>exponential_digits</para></term>
/// <description>A sequence of digits from 0 through 9. For fractional_digits, only the digit 0 is valid.</description>
/// </item>
/// <item>
/// <term>.</term>
/// <description>
/// A culture-specific decimal point symbol.
/// The current culture's decimal point symbol can appear in <paramref name="value"/> if <paramref name="style"/> includes the <see cref="NumberStyles.AllowDecimalPoint"/> flag.
/// </description>
/// </item>
/// <item>
/// <term>,</term>
/// <description>
/// A culture-specific group separator symbol.
/// The current culture's group separator can appear in <paramref name="value"/> if <paramref name="style"/> includes the <see cref="NumberStyles.AllowThousands"/> flag.</description>
/// </item>
/// <item>
/// <term>E</term>
/// <description>
/// The "e" or "E" character, which indicates that the value is represented in exponential (scientific) notation.
/// The <paramref name="value"/> parameter can represent a number in exponential notation if <paramref name="style"/> includes the <see cref="NumberStyles.AllowExponent"/> flag.
/// </description>
/// </item>
/// <item>
/// <term>hexdigits</term>
/// <description>A sequence of hexadecimal digits from 0 through f, or 0 through F.</description>
/// </item>
/// <item><term>hexdigits</term><description>A sequence of hexadecimal digits from 0 through f, or 0 through F.</description></item>
/// </list>
/// A string with decimal digits only (which corresponds to the <see cref="NumberStyles.None"/> style) always parses successfully.
/// Most of the remaining <see cref="NumberStyles"/> members control elements that may be present, but are not required to be present, in this input string.
/// The following table indicates how individual <see cref="NumberStyles"/> members affect the elements that may be present in <paramref name="value"/>.
/// <list type="table">
/// <listheader>
/// <term><see cref="NumberStyles"/> value</term>
/// <description>Elements permitted in <paramref name="value"/> in addition to digits</description>
/// </listheader>
/// <item><term><see cref="NumberStyles.None"/></term><description>The digits element only.</description></item>
/// <item><term><see cref="NumberStyles.AllowDecimalPoint"/></term><description>The decimal point (.) and fractional-digits elements.</description></item>
/// <item><term><see cref="NumberStyles.AllowExponent"/></term><description>The "e" or "E" character, which indicates exponential notation, along with exponential_digits.</description></item>
/// <item><term><see cref="NumberStyles.AllowLeadingWhite"/></term><description>The ws element at the start of <paramref name="value"/>.</description></item>
/// <item><term><see cref="NumberStyles.AllowTrailingWhite"/></term><description>The ws element at the end of <paramref name="value"/>.</description></item>
/// <item><term><see cref="NumberStyles.AllowLeadingSign"/></term><description>The sign element at the start of <paramref name="value"/>.</description></item>
/// <item><term><see cref="NumberStyles.AllowTrailingSign"/></term><description>The sign element at the end of <paramref name="value"/>.</description></item>
/// <item><term><see cref="NumberStyles.AllowParentheses"/></term><description>The sign element in the form of parentheses enclosing the numeric value.</description></item>
/// <item><term><see cref="NumberStyles.AllowThousands"/></term><description>The group separator (,) element. </description></item>
/// <item><term><see cref="NumberStyles.AllowCurrencySymbol"/></term><description>The currency ($) element.</description></item>
/// <item><term><see cref="NumberStyles.Currency"/></term><description>All elements. However, <paramref name="value"/> cannot represent a hexadecimal number or a number in exponential notation.</description></item>
/// <item><term><see cref="NumberStyles.Float"/></term><description>The ws element at the start or end of <paramref name="value"/>, sign at the start of <paramref name="value"/>, and the decimal point (.) symbol. The <paramref name="value"/> parameter can also use exponential notation.</description></item>
/// <item><term><see cref="NumberStyles.Number"/></term><description>The ws, sign, group separator (,), and decimal point (.) elements.</description></item>
/// <item><term><see cref="NumberStyles.Any"/></term><description>All elements. However, <paramref name="value"/> cannot represent a hexadecimal number.</description></item>
/// </list>
/// Unlike the other <see cref="NumberStyles"/> values, which allow for, but do not require, the presence of particular style elements in <paramref name="value"/>, the <see cref="NumberStyles.AllowHexSpecifier"/> style value means that the individual numeric characters in <paramref name="value"/> are always interpreted as hexadecimal characters.
/// Valid hexadecimal characters are 0-9, A-F, and a-f.
/// The only other flags that can be combined with the <paramref name="style"/> parameter are <see cref="NumberStyles.AllowLeadingWhite"/> and <see cref="NumberStyles.AllowTrailingWhite"/>.
/// (The <see cref="NumberStyles"/> enumeration includes a composite number style, <see cref="NumberStyles.HexNumber"/>, that includes both white-space flags.)
/// <note>
/// If <paramref name="value"/> is the string representation of a hexadecimal number, it cannot be preceded by any decoration (such as 0x or &amp;h) that differentiates it as a hexadecimal number.
/// This causes the conversion to fail.
/// </note>
/// The <paramref name="value"/> parameter is parsed by using the formatting information in a <see cref="NumberFormatInfo"/> object that is initialized for the current system culture.
/// To specify the culture whose formatting information is used for the parse operation, call the <see cref="Parse(String, NumberStyles, IFormatProvider)"/> overload.
/// </remarks>
public static UInt48 Parse(string value, NumberStyles style)
{
return Parse(value, style, CultureInfo.CurrentCulture.NumberFormat);
}
/// <summary>
/// Converts the string representation of a number in a specified style and culture-specific format to its 48-bit unsigned integer equivalent.
/// </summary>
/// <param name="value">
/// A string that represents the number to convert.
/// The string is interpreted by using the style specified by the <paramref name="style"/> parameter.
/// </param>
/// <param name="style">
/// A bitwise combination of NumberStyles values that indicates the permitted format of value.
/// A typical value to specify is NumberStyles.Integer.
/// A bitwise combination of enumeration values that indicates the style elements that can be present in <paramref name="value"/>.
/// A typical value to specify is <see cref="NumberStyles.Integer"/>.
/// </param>
/// <param name="provider">An System.IFormatProvider that supplies culture-specific formatting information about value.</param>
/// <returns>A 48-bit unsigned integer equivalent to the number specified in s.</returns>
/// <param name="provider">An object that supplies culture-specific formatting information about <paramref name="value"/>.</param>
/// <returns>A 48-bit unsigned integer equivalent to the number specified in <paramref name="value"/>.</returns>
/// <exception cref="ArgumentNullException">The <paramref name="value"/> parameter is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException">
/// <paramref name="style"/> is not a <see cref="NumberStyles"/> value.
/// <para>-or-</para>
/// <para><paramref name="style"/> is not a combination of <see cref="NumberStyles.AllowHexSpecifier"/> and <see cref="NumberStyles.HexNumber"/> values.</para>
/// </exception>
/// <exception cref="FormatException">The <paramref name="value"/> parameter is not in a format compliant with <paramref name="style"/>.</exception>
/// <exception cref="OverflowException">
/// The <paramref name="value"/> parameter represents a number less than <see cref="UInt48.MinValue"/> or greater than <see cref="UInt48.MaxValue"/>.
/// <para>-or-</para>
/// <para><paramref name="value"/> includes non-zero, fractional digits.</para>
/// </exception>
/// <remarks>
/// The <paramref name="style"/> parameter defines the style elements (such as white space or the positive or negative sign symbol) that are allowed in the s parameter for the parse operation to succeed.
/// It must be a combination of bit flags from the <see cref="NumberStyles"/> enumeration.
/// <para>Depending on the value of style, the <paramref name="value"/> parameter may include the following elements:</para>
/// <para>[ws][$][sign]digits[.fractional_digits][E[sign]exponential_digits][ws]</para>
/// <para>
/// Elements in square brackets ([ and ]) are optional.
/// If <paramref name="style"/> includes <see cref="NumberStyles.AllowHexSpecifier"/>, the <paramref name="value"/> parameter may include the following elements:
/// </para>
/// <para>[ws]hexdigits[ws]</para>
/// <para>The following table describes each element.</para>
/// <list type="table">
/// <listheader>
/// <term>Element</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>ws</term>
/// <description>
/// Optional white space.
/// White space can appear at the beginning of <paramref name="value"/> if <paramref name="style"/> includes the <see cref="NumberStyles.AllowLeadingWhite"/> flag,
/// and it can appear at the end of <paramref name="style"/> if <paramref name="style"/> includes the <see cref="NumberStyles.AllowTrailingWhite"/> flag.
/// </description>
/// </item>
/// <item>
/// <term>$</term>
/// <description>
/// A culture-specific currency symbol.
/// Its position in the string is defined by the <see cref="NumberFormatInfo.CurrencyPositivePattern"/> property of the <see cref="NumberFormatInfo"/> object that is returned by the <see cref="IFormatProvider.GetFormat"/> method of the provider parameter.
/// The currency symbol can appear in <paramref name="value"/> if <paramref name="style"/> includes the <see cref="NumberStyles.AllowCurrencySymbol"/> flag.
/// </description>
/// </item>
/// <item>
/// <term>sign</term>
/// <description>
/// An optional sign.
/// (The method throws an <see cref="OverflowException"/> if <paramref name="value"/> includes a negative sign and represents a non-zero number.)
/// The sign can appear at the beginning of <paramref name="value"/> if <paramref name="style"/> includes the <see cref="NumberStyles.AllowLeadingSign"/> flag, and it can appear the end of <paramref name="value"/> if <paramref name="style"/> includes the <see cref="NumberStyles.AllowTrailingSign"/> flag.
/// Parentheses can be used in <paramref name="value"/> to indicate a negative value if <paramref name="style"/> includes the <see cref="NumberStyles.AllowParentheses"/> flag.
/// </description>
/// </item>
/// <item><term>digits</term><description>A sequence of digits from 0 through 9.</description></item>
/// <item>
/// <term>.</term>
/// <description>
/// A culture-specific decimal point symbol.
/// The current culture's decimal point symbol can appear in <paramref name="value"/> if <paramref name="style"/> includes the <see cref="NumberStyles.AllowDecimalPoint"/> flag.
/// </description>
/// </item>
/// <item>
/// <term>fractional_digits</term>
/// <description>
/// One or more occurrences of the digit 0-9 if <paramref name="style"/> includes the <see cref="NumberStyles.AllowExponent"/> flag,
/// or one or more occurrences of the digit 0 if it does not.
/// Fractional digits can appear in <paramref name="value"/> only if <paramref name="style"/> includes the <see cref="NumberStyles.AllowDecimalPoint"/> flag.
/// </description>
/// </item>
/// <item>
/// <term>E</term>
/// <description>
/// The "e" or "E" character, which indicates that the value is represented in exponential (scientific) notation.
/// The <paramref name="value"/> parameter can represent a number in exponential notation if <paramref name="style"/> includes the <see cref="NumberStyles.AllowExponent"/> flag.
/// </description>
/// </item>
/// <item>
/// <term>exponential_digits</term>
/// <description>
/// A sequence of digits from 0 through 9.
/// The <paramref name="value"/> parameter can represent a number in exponential notation if <paramref name="style"/> includes the <see cref="NumberStyles.AllowExponent"/> flag.
/// </description>
/// </item>
/// <item><term>hexdigits</term><description>A sequence of hexadecimal digits from 0 through f, or 0 through F.</description></item>
/// </list>
/// A string with decimal digits only (which corresponds to the <see cref="NumberStyles.None"/> style) always parses successfully.
/// Most of the remaining <see cref="NumberStyles"/> members control elements that may be present, but are not required to be present, in this input string.
/// The following table indicates how individual <see cref="NumberStyles"/> members affect the elements that may be present in <paramref name="value"/>.
/// <list type="table">
/// <listheader>
/// <term>Non-composite <see cref="NumberStyles"/> values</term>
/// <description>Elements permitted in <paramref name="value"/> in addition to digits</description>
/// </listheader>
/// <item><term><see cref="NumberStyles.None"/></term><description>Decimal digits only.</description></item>
/// <item><term><see cref="NumberStyles.AllowDecimalPoint"/></term><description>The decimal point (.) and fractional_digits elements. However, if <paramref name="style"/> does not include the <see cref="NumberStyles.AllowExponent"/> flag, fractional_digits must consist of only one or more 0 digits; otherwise, an <see cref="OverflowException"/> is thrown.</description></item>
/// <item><term><see cref="NumberStyles.AllowExponent"/></term><description>The "e" or "E" character, which indicates exponential notation, along with exponential_digits.</description></item>
/// <item><term><see cref="NumberStyles.AllowLeadingWhite"/></term><description>The ws element at the beginning of <paramref name="value"/>.</description></item>
/// <item><term><see cref="NumberStyles.AllowTrailingWhite"/></term><description>The ws element at the end of <paramref name="value"/>.</description></item>
/// <item><term><see cref="NumberStyles.AllowLeadingSign"/></term><description>A sign before digits.</description></item>
/// <item><term><see cref="NumberStyles.AllowTrailingSign"/></term><description>A sign after digits.</description></item>
/// <item><term><see cref="NumberStyles.AllowParentheses"/></term><description>Parentheses before and after digits to indicate a negative value.</description></item>
/// <item><term><see cref="NumberStyles.AllowThousands"/></term><description>The group separator (,) element. </description></item>
/// <item><term><see cref="NumberStyles.AllowCurrencySymbol"/></term><description>The currency ($) element.</description></item>
/// </list>
/// If the <see cref="NumberStyles.AllowHexSpecifier"/> flag is used, <paramref name="value"/> must be a hexadecimal value.
/// The only other flags that can be combined with it are <see cref="NumberStyles.AllowLeadingWhite"/> and <see cref="NumberStyles.AllowTrailingWhite"/>.
/// (The <see cref="NumberStyles"/> enumeration includes a composite number style, <see cref="NumberStyles.HexNumber"/>, that includes both white-space flags.)
/// <note>
/// If the <paramref name="value"/> parameter is the string representation of a hexadecimal number, it cannot be preceded by any decoration (such as 0x or &amp;h) that differentiates it as a hexadecimal number.
/// This causes the parse operation to throw an exception.
/// </note>
/// The <paramref name="provider"/> parameter is an <see cref="IFormatProvider"/> implementation whose <see cref="IFormatProvider.GetFormat"/> method returns a <see cref="NumberFormatInfo"/> object that provides culture-specific information about the format of <paramref name="value"/>.
/// There are three ways to use the <paramref name="provider"/> parameter to supply custom formatting information to the parse operation:
/// <list type="bullet">
/// <item>You can pass the actual <see cref="NumberFormatInfo"/> object that provides formatting information. (Its implementation of <see cref="IFormatProvider.GetFormat"/> simply returns itself.)</item>
/// <item>You can pass a <see cref="CultureInfo"/> object that specifies the culture whose formatting is to be used. Its <see cref="CultureInfo.NumberFormat"/> property provides formatting information.</item>
/// <item>You can pass a custom <see cref="IFormatProvider"/> implementation. Its <see cref="IFormatProvider.GetFormat"/> method must instantiate and return the <see cref="NumberFormatInfo"/> object that provides formatting information.</item>
/// </list>
/// If provider is <see langword="null"/>, the <see cref="NumberFormatInfo"/> object for the current culture is used.
/// </remarks>
public static UInt48 Parse(string value, NumberStyles style, IFormatProvider provider)
{
ulong parsedValue = ulong.Parse(value, style, provider);
ulong parsedValue;
try
{
parsedValue = ulong.Parse(value, style, provider);
}
catch (OverflowException)
{
throw new OverflowException("Value was either too large or too small for a UInt48");
}
if (parsedValue > MaxValue)
throw new FormatException("parsed value " + parsedValue + " is larger than max value " + MaxValue);
throw new OverflowException("Value was too large for a UInt48");
return (UInt48)parsedValue;
}
......
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading;
......@@ -73,7 +74,7 @@ namespace PcapDotNet.Core.Test
Assert.AreEqual(PacketCommunicatorReceiveResult.Timeout, result);
Assert.AreEqual<uint>(0, communicator.TotalStatistics.PacketsCaptured);
MoreAssert.IsInRange(TimeSpan.FromSeconds(0.99), TimeSpan.FromSeconds(1.04), finishedWaiting - startWaiting);
MoreAssert.IsInRange(TimeSpan.FromSeconds(0.99), TimeSpan.FromSeconds(1.075), finishedWaiting - startWaiting);
Packet sentPacket = _random.NextEthernetPacket(24, SourceMac, DestinationMac);
......@@ -134,7 +135,7 @@ namespace PcapDotNet.Core.Test
TestReceivePackets(NumPacketsToSend, NumPacketsToSend + 1, int.MaxValue, 2, PacketSize, PacketCommunicatorReceiveResult.None, NumPacketsToSend, 2, 2.035);
// Break loop
TestReceivePackets(NumPacketsToSend, NumPacketsToSend, 0, 2, PacketSize, PacketCommunicatorReceiveResult.BreakLoop, 0, 0, 0.02);
TestReceivePackets(NumPacketsToSend, NumPacketsToSend, 0, 2, PacketSize, PacketCommunicatorReceiveResult.BreakLoop, 0, 0, 0.027);
TestReceivePackets(NumPacketsToSend, NumPacketsToSend, NumPacketsToSend / 2, 2, PacketSize, PacketCommunicatorReceiveResult.BreakLoop, NumPacketsToSend / 2, 0, 0.02);
}
......@@ -148,11 +149,11 @@ namespace PcapDotNet.Core.Test
TestReceivePacketsEnumerable(NumPacketsToSend, NumPacketsToSend, int.MaxValue, 2, PacketSize, NumPacketsToSend, 0, 0.3);
// Wait for less packets
TestReceivePacketsEnumerable(NumPacketsToSend, NumPacketsToSend / 2, int.MaxValue, 2, PacketSize, NumPacketsToSend / 2, 0, 0.02);
TestReceivePacketsEnumerable(NumPacketsToSend, NumPacketsToSend / 2, int.MaxValue, 2, PacketSize, NumPacketsToSend / 2, 0, 0.027);
// Wait for more packets
TestReceivePacketsEnumerable(NumPacketsToSend, -1, int.MaxValue, 2, PacketSize, NumPacketsToSend, 2, 2.02);
TestReceivePacketsEnumerable(NumPacketsToSend, NumPacketsToSend + 1, int.MaxValue, 2, PacketSize, NumPacketsToSend, 2, 2.03);
TestReceivePacketsEnumerable(NumPacketsToSend, NumPacketsToSend + 1, int.MaxValue, 2, PacketSize, NumPacketsToSend, 2, 2.13);
// Break loop
TestReceivePacketsEnumerable(NumPacketsToSend, NumPacketsToSend, 0, 2, PacketSize, 0, 0, 0.02);
......@@ -538,6 +539,9 @@ namespace PcapDotNet.Core.Test
communicator.SetFilter("ether src " + sourceMac + " and ether dst " + destinationMac);
communicator.SetSamplingMethod(new SamplingMethodFirstAfterInterval(TimeSpan.FromSeconds(1)));
Packet expectedPacket = _random.NextEthernetPacket(60, sourceMac, destinationMac);
List<Packet> packets = new List<Packet>(6);
Thread thread = new Thread(() => packets.AddRange(communicator.ReceivePackets(6)));
thread.Start();
communicator.SendPacket(expectedPacket);
Thread.Sleep(TimeSpan.FromSeconds(0.75));
for (int i = 0; i != 10; ++i)
......@@ -547,15 +551,18 @@ namespace PcapDotNet.Core.Test
Thread.Sleep(TimeSpan.FromSeconds(0.5));
}
if (!thread.Join(TimeSpan.FromSeconds(10)))
thread.Abort();
Assert.AreEqual(6, packets.Count);
Packet packet;
PacketCommunicatorReceiveResult result;
for (int i = 0; i != 6; ++i)
{
result = communicator.ReceivePacket(out packet);
Assert.AreEqual(PacketCommunicatorReceiveResult.Ok, result);
Assert.AreEqual(60 * (i * 2 + 1), packet.Length);
// result = communicator.ReceivePacket(out packet);
// Assert.AreEqual(PacketCommunicatorReceiveResult.Ok, result);
// Assert.AreEqual(60 * (i * 2 + 1), packet.Length, i.ToString());
Assert.AreEqual(60 * (i * 2 + 1), packets[i].Length, i.ToString());
}
result = communicator.ReceivePacket(out packet);
PacketCommunicatorReceiveResult result = communicator.ReceivePacket(out packet);
Assert.AreEqual(PacketCommunicatorReceiveResult.Timeout, result);
Assert.IsNull(packet);
}
......@@ -601,6 +608,26 @@ namespace PcapDotNet.Core.Test
}
}
[TestMethod]
[ExpectedException(typeof(InvalidOperationException))]
public void SetInvalidDataLink()
{
using (PacketCommunicator communicator = OpenLiveDevice())
{
communicator.DataLink = new PcapDataLink(0);
Assert.AreEqual(new PcapDataLink(0), communicator.DataLink);
}
}
[TestMethod]
public void SendZeroPacket()
{
using (PacketCommunicator communicator = OpenLiveDevice())
{
communicator.SendPacket(new Packet(new byte[0], DateTime.Now, DataLinkKind.Ethernet));
}
}
private static void TestGetStatistics(string sourceMac, string destinationMac, int numPacketsToSend, int numStatisticsToGather, int numStatisticsToBreakLoop, double secondsToWait, int packetSize,
PacketCommunicatorReceiveResult expectedResult, int expectedNumStatistics, int expectedNumPackets, double expectedMinSeconds, double expectedMaxSeconds)
{
......@@ -817,7 +844,9 @@ namespace PcapDotNet.Core.Test
Assert.AreNotEqual(null, totalStatistics);
Assert.AreEqual(totalStatistics.GetHashCode(), totalStatistics.GetHashCode());
Assert.IsTrue(totalStatistics.Equals(totalStatistics));
Assert.IsFalse(totalStatistics.Equals(null));
Assert.AreNotEqual(null, totalStatistics);
Assert.AreNotEqual(totalStatistics, 2);
MoreAssert.IsSmallerOrEqual<uint>(1, totalStatistics.PacketsCaptured, "PacketsCaptured");
Assert.AreEqual<uint>(0, totalStatistics.PacketsDroppedByDriver, "PacketsDroppedByDriver");
Assert.AreEqual<uint>(0, totalStatistics.PacketsDroppedByInterface, "PacketsDroppedByInterface");
......
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Packets;
......
......@@ -115,10 +115,14 @@ namespace PcapDotNet.Core.Test
dataLinkName = dataLink.Name;
Assert.IsNotNull(dataLinkName);
}
catch (ArgumentException)
catch (InvalidOperationException)
{
return dataLink;
}
catch (Exception)
{
Assert.Fail();
}
}
Assert.Fail();
return new PcapDataLink();
......
......@@ -182,10 +182,20 @@ namespace PcapDotNet.Core.Test
private static void ComparePacketsToWireshark(IEnumerable<Packet> packets)
{
string pcapFilename = Path.GetTempPath() + "temp." + new Random().NextByte() + ".pcap";
PacketDumpFile.Dump(pcapFilename, new PcapDataLink(DataLinkKind.Ethernet), PacketDevice.DefaultSnapshotLength, packets);
// List<Packet> packetsList = new List<Packet>();
// new OfflinePacketDevice(pcapFilename).Open().ReceivePackets(1000, packetsList.Add);
// packets = packetsList;
// const bool isRetry = true;
const bool isRetry = false;
if (!isRetry)
{
PacketDumpFile.Dump(pcapFilename, new PcapDataLink(DataLinkKind.Ethernet), PacketDevice.DefaultSnapshotLength, packets);
}
else
{
const byte retryNumber = 24;
pcapFilename = Path.GetTempPath() + "temp." + retryNumber + ".pcap";
List<Packet> packetsList = new List<Packet>();
new OfflinePacketDevice(pcapFilename).Open().ReceivePackets(1000, packetsList.Add);
packets = packetsList;
}
// Create pdml file
string documentFilename = pcapFilename + ".pdml";
......
......@@ -101,40 +101,5 @@ namespace PcapDotNet.Packets.Test
Assert.AreEqual(0x02, buffer[2]);
Assert.AreEqual(0x01, buffer[3]);
}
[TestMethod]
public void UInt48Test()
{
UInt48 value = (UInt48)0x010203040506;
byte[] buffer = new byte[UInt48.SizeOf];
buffer.Write(0, value, Endianity.Big);
Assert.AreEqual(value, buffer.ReadUInt48(0, Endianity.Big));
Assert.AreEqual(0x01, buffer[0]);
Assert.AreEqual(0x02, buffer[1]);
Assert.AreEqual(0x03, buffer[2]);
Assert.AreEqual(0x04, buffer[3]);
Assert.AreEqual(0x05, buffer[4]);
Assert.AreEqual(0x06, buffer[5]);
int offset = 0;
buffer.Write(ref offset, value, Endianity.Big);
Assert.AreEqual(value, buffer.ReadUInt48(0, Endianity.Big));
Assert.AreEqual(6, offset);
buffer.Write(0, value, Endianity.Small);
Assert.AreEqual(value, buffer.ReadUInt48(0, Endianity.Small));
Assert.AreEqual(0x06, buffer[0]);
Assert.AreEqual(0x05, buffer[1]);
Assert.AreEqual(0x04, buffer[2]);
Assert.AreEqual(0x03, buffer[3]);
Assert.AreEqual(0x02, buffer[4]);
Assert.AreEqual(0x01, buffer[5]);
offset = 0;
buffer.Write(ref offset, value, Endianity.Small);
Assert.AreEqual(value, buffer.ReadUInt48(0, Endianity.Small));
Assert.AreEqual(6, offset);
}
}
}
\ No newline at end of file
......@@ -3,7 +3,7 @@ using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.TestUtils;
using PcapDotNet.TestUtils;
using PcapDotNet.Packets.Transport;
namespace PcapDotNet.Packets.Test
{
......@@ -77,5 +77,21 @@ namespace PcapDotNet.Packets.Test
Assert.AreEqual(payloadLayer.Data, packet.Ethernet.Payload);
}
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void AutomaticEthernetTypeNoNextLayer()
{
Packet packet = PacketBuilder.Build(DateTime.Now, new EthernetLayer());
Assert.IsTrue(packet.IsValid);
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void AutomaticEthernetTypeBadNextLayer()
{
Packet packet = PacketBuilder.Build(DateTime.Now, new EthernetLayer(), new TcpLayer());
Assert.IsTrue(packet.IsValid);
}
}
}
\ No newline at end of file
......@@ -136,6 +136,7 @@ namespace PcapDotNet.Packets.Test
foreach (GreSourceRouteEntry entry in actualGre.Routing)
{
Assert.AreNotEqual(entry, 2);
Assert.AreEqual(entry.GetHashCode(), entry.GetHashCode());
switch (entry.AddressFamily)
{
case GreSourceRouteEntryAddressFamily.AsSourceRoute:
......@@ -179,6 +180,29 @@ namespace PcapDotNet.Packets.Test
}
}
[TestMethod]
public void GreAutomaticProtocolType()
{
Packet packet = PacketBuilder.Build(DateTime.Now, new EthernetLayer(), new IpV4Layer(), new GreLayer(), new IpV4Layer(), new IcmpEchoLayer());
Assert.IsTrue(packet.IsValid);
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void GreAutomaticProtocolTypeNoNextLayer()
{
Packet packet = PacketBuilder.Build(DateTime.Now, new EthernetLayer(), new IpV4Layer(), new GreLayer());
Assert.IsTrue(packet.IsValid);
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void GreAutomaticProtocolTypeBadNextLayer()
{
Packet packet = PacketBuilder.Build(DateTime.Now, new EthernetLayer(), new IpV4Layer(), new GreLayer(), new PayloadLayer());
Assert.IsTrue(packet.IsValid);
}
[TestMethod]
public void InvalidGreTest()
{
......@@ -204,7 +228,7 @@ namespace PcapDotNet.Packets.Test
PacketBuilder packetBuilder = new PacketBuilder(ethernetLayer, ipV4Layer, greLayer);
Packet packet = packetBuilder.Build(DateTime.Now);
Assert.IsTrue(packet.IsValid);
Assert.IsTrue(packet.IsValid, "IsValid");
GreDatagram gre = packet.Ethernet.IpV4.Gre;
......
......@@ -138,7 +138,18 @@ namespace PcapDotNet.Packets.Gre
/// <param name="nextLayer">The layer that comes after this layer. null if this is the last layer.</param>
public override void Write(byte[] buffer, int offset, int payloadLength, ILayer previousLayer, ILayer nextLayer)
{
GreDatagram.WriteHeader(buffer, offset, RecursionControl, FutureUseBits, Version, ProtocolType, ChecksumPresent, Key, SequenceNumber, AcknowledgmentSequenceNumber, Routing, RoutingOffset, StrictSourceRoute);
EthernetType protocolType = ProtocolType;
if (protocolType == EthernetType.None)
{
if (nextLayer == null)
throw new ArgumentException("Can't determine protocol type automatically from next layer because there is not next layer");
IEthernetNextLayer ethernetNextLayer = nextLayer as IEthernetNextLayer;
if (ethernetNextLayer == null)
throw new ArgumentException("Can't determine protocol type automatically from next layer (" + nextLayer.GetType() + ")");
protocolType = ethernetNextLayer.PreviousLayerEtherType;
}
GreDatagram.WriteHeader(buffer, offset, RecursionControl, FutureUseBits, Version, protocolType, ChecksumPresent, Key, SequenceNumber, AcknowledgmentSequenceNumber, Routing, RoutingOffset, StrictSourceRoute);
}
/// <summary>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment