Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit c80e1a9

Browse files
committed
Merge pull request #2063 from ellismg/textinfo-unit-tests
Add TextInfo casing tests
2 parents b429873 + eea46fa commit c80e1a9

File tree

5 files changed

+910
-0
lines changed

5 files changed

+910
-0
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio 2013
4+
VisualStudioVersion = 12.0.31101.0
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Globalization.Tests", "tests\System.Globalization.Tests.csproj", "{7F5F5134-00FE-4DE8-B20C-3DA8BA2EBA68}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{7F5F5134-00FE-4DE8-B20C-3DA8BA2EBA68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{7F5F5134-00FE-4DE8-B20C-3DA8BA2EBA68}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{7F5F5134-00FE-4DE8-B20C-3DA8BA2EBA68}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{7F5F5134-00FE-4DE8-B20C-3DA8BA2EBA68}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
EndGlobal
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
4+
<PropertyGroup>
5+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7+
<ProjectGuid>{7F5F5134-00FE-4DE8-B20C-3DA8BA2EBA68}</ProjectGuid>
8+
<OutputType>Library</OutputType>
9+
<RootNamespace>System.Globalization.Tests</RootNamespace>
10+
<AssemblyName>System.Globalization.Tests</AssemblyName>
11+
<RestorePackages>true</RestorePackages>
12+
</PropertyGroup>
13+
<!-- Default configurations to help VS understand the configurations -->
14+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
15+
</PropertyGroup>
16+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
17+
</PropertyGroup>
18+
<ItemGroup>
19+
<Compile Include="TextInfo.cs" />
20+
</ItemGroup>
21+
<ItemGroup>
22+
<None Include="project.json" />
23+
</ItemGroup>
24+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
25+
</Project>
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Globalization;
6+
using Xunit;
7+
8+
public class TextInfoTests
9+
{
10+
[Theory]
11+
[InlineData("")]
12+
[InlineData("en-US")]
13+
[InlineData("fr")]
14+
[ActiveIssue(846, PlatformID.AnyUnix)]
15+
public static void ToUpper(string localeName)
16+
{
17+
TextInfo ti = new CultureInfo(localeName).TextInfo;
18+
19+
Assert.Equal('A', ti.ToUpper('a'));
20+
Assert.Equal("ABC", ti.ToUpper("abc"));
21+
Assert.Equal('A', ti.ToUpper('A'));
22+
Assert.Equal("ABC", ti.ToUpper("ABC"));
23+
24+
Assert.Equal("THIS IS A LONGER TEST CASE", ti.ToUpper("this is a longer test case"));
25+
Assert.Equal("THIS IS A LONGER MIXED CASE TEST CASE", ti.ToUpper("this Is A LONGER mIXEd casE test case"));
26+
27+
Assert.Equal("THIS \t HAS \t SOME \t TABS", ti.ToUpper("this \t HaS \t somE \t TABS"));
28+
29+
Assert.Equal('1', ti.ToUpper('1'));
30+
Assert.Equal("123", ti.ToUpper("123"));
31+
32+
Assert.Equal("EMBEDDED\0NULL\0BYTE\0", ti.ToUpper("embedded\0NuLL\0Byte\0"));
33+
34+
// LATIN SMALL LETTER O WITH ACUTE, which has an upper case variant.
35+
Assert.Equal('\u00D3', ti.ToUpper('\u00F3'));
36+
Assert.Equal("\u00D3", ti.ToUpper("\u00F3"));
37+
38+
// SNOWMAN, which does not have an upper case variant.
39+
Assert.Equal('\u2603', ti.ToUpper('\u2603'));
40+
Assert.Equal("\u2603", ti.ToUpper("\u2603"));
41+
42+
// DESERT SMALL LETTER LONG I has an upperc case variant.
43+
Assert.Equal("\U00010400", ti.ToUpper("\U00010428"));
44+
45+
// RAINBOW (outside the BMP and does not case)
46+
Assert.Equal("\U0001F308", ti.ToLower("\U0001F308"));
47+
48+
// These are cases where we have invalid UTF-16 in a string (mismatched surrogate pairs). They should be
49+
// unchanged by casing.
50+
Assert.Equal("BE CAREFUL, \uD83C\uD83C, THIS ONE IS TRICKY", ti.ToUpper("be careful, \uD83C\uD83C, this one is tricky"));
51+
Assert.Equal("BE CAREFUL, \uDF08\uD83C, THIS ONE IS TRICKY", ti.ToUpper("be careful, \uDF08\uD83C, this one is tricky"));
52+
Assert.Equal("BE CAREFUL, \uDF08\uDF08, THIS ONE IS TRICKY", ti.ToUpper("be careful, \uDF08\uDF08, this one is tricky"));
53+
54+
Assert.Throws<ArgumentNullException>(() => ti.ToUpper(null));
55+
}
56+
57+
[Theory]
58+
[InlineData("")]
59+
[InlineData("en-US")]
60+
[InlineData("fr")]
61+
[ActiveIssue(846, PlatformID.AnyUnix)]
62+
public static void ToLower(string localeName)
63+
{
64+
TextInfo ti = new CultureInfo(localeName).TextInfo;
65+
66+
Assert.Equal('a', ti.ToLower('A'));
67+
Assert.Equal("abc", ti.ToLower("ABC"));
68+
Assert.Equal('a', ti.ToLower('a'));
69+
Assert.Equal("abc", ti.ToLower("abc"));
70+
71+
Assert.Equal("this is a longer test case", ti.ToLower("THIS IS A LONGER TEST CASE"));
72+
Assert.Equal("this is a longer mixed case test case", ti.ToLower("this Is A LONGER mIXEd casE test case"));
73+
74+
Assert.Equal("this \t has \t some \t tabs", ti.ToLower("THIS \t hAs \t SOMe \t tabs"));
75+
76+
Assert.Equal('1', ti.ToLower('1'));
77+
Assert.Equal("123", ti.ToLower("123"));
78+
79+
Assert.Equal("embedded\0null\0byte\0", ti.ToLower("EMBEDDED\0NuLL\0Byte\0"));
80+
81+
// LATIN CAPITAL LETTER O WITH ACUTE, which has a lower case variant.
82+
Assert.Equal('\u00F3', ti.ToLower('\u00D3'));
83+
Assert.Equal("\u00F3", ti.ToLower("\u00D3"));
84+
85+
// SNOWMAN, which does not have a lower case variant.
86+
Assert.Equal('\u2603', ti.ToLower('\u2603'));
87+
Assert.Equal("\u2603", ti.ToLower("\u2603"));
88+
89+
// DESERT CAPITAL LETTER LONG I has a lower case variant.
90+
Assert.Equal("\U00010428", ti.ToLower("\U00010400"));
91+
92+
// RAINBOW (outside the BMP and does not case)
93+
Assert.Equal("\U0001F308", ti.ToLower("\U0001F308"));
94+
95+
// These are cases where we have invalid UTF-16 in a string (mismatched surrogate pairs). They should be
96+
// unchanged by casing.
97+
Assert.Equal("be careful, \uD83C\uD83C, this one is tricky", ti.ToLower("BE CAREFUL, \uD83C\uD83C, THIS ONE IS TRICKY"));
98+
Assert.Equal("be careful, \uDF08\uD83C, this one is tricky", ti.ToLower("BE CAREFUL, \uDF08\uD83C, THIS ONE IS TRICKY"));
99+
Assert.Equal("be careful, \uDF08\uDF08, this one is tricky", ti.ToLower("BE CAREFUL, \uDF08\uDF08, THIS ONE IS TRICKY"));
100+
101+
Assert.Throws<ArgumentNullException>(() => ti.ToLower(null));
102+
}
103+
104+
[Theory]
105+
[InlineData("tr")]
106+
[InlineData("tr-TR")]
107+
[InlineData("az")]
108+
[InlineData("az-Latn-AZ")]
109+
[ActiveIssue(846, PlatformID.AnyUnix)]
110+
public static void TurkishICasing(string localeName)
111+
{
112+
TextInfo ti = new CultureInfo(localeName).TextInfo;
113+
114+
Assert.Equal('i', ti.ToLower('\u0130'));
115+
Assert.Equal("i", ti.ToLower("\u0130"));
116+
117+
Assert.Equal('\u0130', ti.ToUpper('i'));
118+
Assert.Equal("\u0130", ti.ToUpper("i"));
119+
120+
Assert.Equal('\u0131', ti.ToLower('I'));
121+
Assert.Equal("\u0131", ti.ToLower("I"));
122+
123+
Assert.Equal('I', ti.ToUpper('\u0131'));
124+
Assert.Equal("I", ti.ToUpper("\u0131"));
125+
}
126+
127+
[Theory]
128+
[InlineData("")]
129+
[InlineData("en-US")]
130+
[InlineData("fr-FR")]
131+
[ActiveIssue(846, PlatformID.AnyUnix)]
132+
public static void NoUnicodeSpecalCases(string localeName)
133+
{
134+
// Unicode defines some codepoints which expand into multiple codepoints
135+
// when cased (see SpecialCasing.txt from UNIDATA for some examples). We have never done
136+
// these sorts of expansions, since it would cause string lengths to change when cased,
137+
// which is non-intuative. In addition, there are some context sensitive mappings which
138+
// we also don't preform.
139+
140+
TextInfo ti = new CultureInfo(localeName).TextInfo;
141+
142+
// es-zed does not case to SS when upercased.
143+
Assert.Equal("\u00DF", ti.ToUpper("\u00DF"));
144+
145+
// Ligatures do not expand when cased.
146+
Assert.Equal("\uFB00", ti.ToUpper("\uFB00"));
147+
148+
// Precomposed character with no uppercase variaint, we don't want to "decompose" this
149+
// as part of casing.
150+
Assert.Equal("\u0149", ti.ToUpper("\u0149"));
151+
152+
// Greek Capital Letter Sigma (does not to case to U+03C2 with "final sigma" rule).
153+
Assert.Equal("\u03C3", ti.ToLower("\u03A3"));
154+
}
155+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"dependencies": {
3+
"System.Console": "4.0.0-beta-*",
4+
"System.Globalization": "4.0.10-beta-*",
5+
"System.Reflection": "4.0.10-beta-*",
6+
"System.Runtime": "4.0.20-beta-*",
7+
"System.Runtime.Extensions": "4.0.10-beta-*",
8+
"System.Runtime.InteropServices": "4.0.20-beta-*",
9+
"System.Threading": "4.0.10-beta-*",
10+
"System.Threading.Tasks": "4.0.10-beta-*",
11+
"xunit": "2.0.0-beta5-build2785",
12+
"xunit.abstractions.netcore": "1.0.0-prerelease",
13+
"xunit.assert": "2.0.0-beta5-build2785",
14+
"xunit.core.netcore": "1.0.1-prerelease",
15+
"xunit.netcore.extensions": "1.0.0-prerelease-*"
16+
},
17+
"frameworks": {
18+
"dnxcore50": {}
19+
}
20+
}

0 commit comments

Comments
 (0)