diff --git a/.gitignore b/.gitignore index 7f2e43bd..eb52d2c0 100644 --- a/.gitignore +++ b/.gitignore @@ -41,4 +41,5 @@ artifacts/* *.nuget.targets *.lock.json *.nuget.props +*.DotSettings.user diff --git a/src/CommandLine/Core/TypeConverter.cs b/src/CommandLine/Core/TypeConverter.cs index 2cec8ada..ad2b7d81 100644 --- a/src/CommandLine/Core/TypeConverter.cs +++ b/src/CommandLine/Core/TypeConverter.cs @@ -84,7 +84,7 @@ private static Result ChangeTypeScalarImpl(string value, Type return (value == null) ? empty() : withValue(); }; - return value.IsBooleanString() + return value.IsBooleanString() && conversionType == typeof(bool) ? value.ToBoolean() : conversionType.GetTypeInfo().IsEnum ? value.ToEnum(conversionType, ignoreValueCase) : safeChangeType(); }; diff --git a/tests/CommandLine.Tests/CommandLine.Tests.csproj b/tests/CommandLine.Tests/CommandLine.Tests.csproj index f3c6925b..dfcc5c1e 100644 --- a/tests/CommandLine.Tests/CommandLine.Tests.csproj +++ b/tests/CommandLine.Tests/CommandLine.Tests.csproj @@ -112,6 +112,7 @@ Code + diff --git a/tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs b/tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs new file mode 100644 index 00000000..7642a80a --- /dev/null +++ b/tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs @@ -0,0 +1,111 @@ +using System; +using System.CodeDom; +using System.Collections.Generic; +using System.Dynamic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using CommandLine.Core; +using CSharpx; +using FluentAssertions; +using Xunit; + +namespace CommandLine.Tests.Unit.Core +{ + public class TypeConverterTests + { + enum TestEnum + { + ValueA = 1, + ValueB = 2 + } + + [Theory] + [MemberData("ChangeType_scalars_source")] + public void ChangeType_scalars(string testValue, Type destinationType, bool expectFail, object expectedResult) + { + Maybe result = TypeConverter.ChangeType(new[] {testValue}, destinationType, true, CultureInfo.InvariantCulture, true); + + if (expectFail) + { + result.MatchNothing().Should().BeTrue("should fail parsing"); + } + else + { + object matchedValue; + + result.MatchJust(out matchedValue).Should().BeTrue("should parse successfully"); + Assert.Equal(matchedValue, expectedResult); + } + } + + public static IEnumerable ChangeType_scalars_source + { + get + { + return new[] + { + new object[] {"1", typeof (int), false, 1}, + new object[] {"0", typeof (int), false, 0}, + new object[] {"-1", typeof (int), false, -1}, + new object[] {"abcd", typeof (int), true, null}, + new object[] {"1.0", typeof (int), true, null}, + new object[] {int.MaxValue.ToString(), typeof (int), false, int.MaxValue}, + new object[] {int.MinValue.ToString(), typeof (int), false, int.MinValue}, + new object[] {((long) int.MaxValue + 1).ToString(), typeof (int), true, null}, + new object[] {((long) int.MinValue - 1).ToString(), typeof (int), true, null}, + + new object[] {"1", typeof (uint), false, (uint) 1}, + new object[] {"0", typeof (uint), false, (uint) 0}, + new object[] {"-1", typeof (uint), true, null}, + new object[] {uint.MaxValue.ToString(), typeof (uint), false, uint.MaxValue}, + new object[] {uint.MinValue.ToString(), typeof (uint), false, uint.MinValue}, + new object[] {((long) uint.MaxValue + 1).ToString(), typeof (uint), true, null}, + new object[] {((long) uint.MinValue - 1).ToString(), typeof (uint), true, null}, + + new object[] {"true", typeof (bool), false, true}, + new object[] {"True", typeof (bool), false, true}, + new object[] {"TRUE", typeof (bool), false, true}, + new object[] {"false", typeof (bool), false, false}, + new object[] {"False", typeof (bool), false, false}, + new object[] {"FALSE", typeof (bool), false, false}, + new object[] {"abcd", typeof (bool), true, null}, + new object[] {"0", typeof (bool), true, null}, + new object[] {"1", typeof (bool), true, null}, + + new object[] {"1.0", typeof (float), false, 1.0f}, + new object[] {"0.0", typeof (float), false, 0.0f}, + new object[] {"-1.0", typeof (float), false, -1.0f}, + new object[] {"abcd", typeof (float), true, null}, + + new object[] {"1.0", typeof (double), false, 1.0}, + new object[] {"0.0", typeof (double), false, 0.0}, + new object[] {"-1.0", typeof (double), false, -1.0}, + new object[] {"abcd", typeof (double), true, null}, + + new object[] {"1.0", typeof (decimal), false, 1.0m}, + new object[] {"0.0", typeof (decimal), false, 0.0m}, + new object[] {"-1.0", typeof (decimal), false, -1.0m}, + new object[] {"-1.123456", typeof (decimal), false, -1.123456m}, + new object[] {"abcd", typeof (decimal), true, null}, + + new object[] {"", typeof (string), false, ""}, + new object[] {"abcd", typeof (string), false, "abcd"}, + + new object[] {"ValueA", typeof (TestEnum), false, TestEnum.ValueA}, + new object[] {"VALUEA", typeof (TestEnum), false, TestEnum.ValueA}, + new object[] {"ValueB", typeof(TestEnum), false, TestEnum.ValueB}, + new object[] {((int) TestEnum.ValueA).ToString(), typeof (TestEnum), false, TestEnum.ValueA}, + new object[] {((int) TestEnum.ValueB).ToString(), typeof (TestEnum), false, TestEnum.ValueB}, + new object[] {((int) TestEnum.ValueB + 1).ToString(), typeof (TestEnum), true, null}, + new object[] {((int) TestEnum.ValueA - 1).ToString(), typeof (TestEnum), true, null}, + + // Failed before #339 + new object[] {"false", typeof (int), true, 0}, + new object[] {"true", typeof (int), true, 0} + }; + } + } + } +}