Skip to content
This repository has been archived by the owner on Dec 18, 2017. It is now read-only.

K Desktop CLR runtime behaves different on string comparison options than core runtime and windows console app #600

Closed
xqiu opened this issue Sep 4, 2014 · 10 comments
Assignees
Milestone

Comments

@xqiu
Copy link

xqiu commented Sep 4, 2014

Was using VS14 CTP3

  1. create a C# ASP.NET VNext Console Project
  2. copy/paste the following code which ported from http://msdn.microsoft.com/en-us/library/system.stringcomparer(v=vs.110).aspx, to make it run for both desktop CLR and core CLR. Also create a windows console app and compare the result.

Actual:

The code generate the same result under the following:

  1. Normal .net45 console app
  2. corerun.exe result (corerun and test.exe are provided from CLR team)
  3. k run (under Core CLR using kvm).

But the code generate the wrong result in
K run (under desktop CLR using kvm)

Here's the code

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create a list of string.
            List<string> list = new List<string>();

            // Get the tr-TR (Turkish-Turkey) culture.
            CultureInfo turkish = new CultureInfo("tr-TR");

            // Get the culture that is associated with the current thread.
            //CultureInfo thisCulture = Thread.CurrentThread.CurrentCulture;
            CultureInfo thisCulture = CultureInfo.CurrentCulture;

            // Get the standard StringComparers.
#if ASPNETCORE50
            StringComparer invCmp = CultureInfo.InvariantCulture.CompareInfo.GetStringComparer(CompareOptions.None);
            StringComparer invICCmp = CultureInfo.InvariantCulture.CompareInfo.GetStringComparer(CompareOptions.IgnoreCase);
#else       
            StringComparer invCmp = StringComparer.InvariantCulture;
            StringComparer invICCmp = StringComparer.InvariantCultureIgnoreCase;
#endif
            StringComparer currCmp = StringComparer.CurrentCulture;
            StringComparer currICCmp = StringComparer.CurrentCultureIgnoreCase;
            StringComparer ordCmp = StringComparer.Ordinal;
            StringComparer ordICCmp = StringComparer.OrdinalIgnoreCase;

            // Create a StringComparer that uses the Turkish culture and ignores case.
#if ASPNETCORE50
            StringComparer turkICComp = CompareInfo.GetCompareInfo(turkish.Name).GetStringComparer(CompareOptions.IgnoreCase);
#else
            StringComparer turkICComp = StringComparer.Create(turkish, true);
#endif

            // Define three strings consisting of different versions of the letter I. 
            // LATIN CAPITAL LETTER I (U+0049) 
            string capitalLetterI = "I";

            // LATIN SMALL LETTER I (U+0069) 
            string smallLetterI = "i";

            // LATIN SMALL LETTER DOTLESS I (U+0131) 
            string smallLetterDotlessI = "\u0131";

            // Add the three strings to the list.
            list.Add(capitalLetterI);
            list.Add(smallLetterI);
            list.Add(smallLetterDotlessI);

            // Display the original list order.
            Display(list, "The original order of the list entries...");

            //Sort the list using the invariant culture.
            list.Sort(invCmp);
            Display(list, "Invariant culture...");
            list.Sort(invICCmp);
            Display(list, "Invariant culture, ignore case...");

            // Sort the list using the current culture.
            Console.WriteLine("The current culture is \"{0}\".", thisCulture.Name);
            list.Sort(currCmp);
            Display(list, "Current culture...");
            list.Sort(currICCmp);
            Display(list, "Current culture, ignore case...");

            // Sort the list using the ordinal value of the character code points.
            list.Sort(ordCmp);
            Display(list, "Ordinal...");
            list.Sort(ordICCmp);
            Display(list, "Ordinal, ignore case...");

            // Sort the list using the Turkish culture, which treats LATIN SMALL LETTER  
            // DOTLESS I differently than LATIN SMALL LETTER I.
            list.Sort(turkICComp);
            Display(list, "Turkish culture, ignore case...");
        }

        public static void Display(List<string> lst, string title)
        {
            Char c;
            int codePoint;
            Console.WriteLine(title);
            foreach (string s in lst)
            {
                c = s[0];
                codePoint = Convert.ToInt32(c);
                Console.WriteLine("0x{0:x}", codePoint);
            }
            Console.WriteLine();
        }
    }
}

Here's the result diff
The original order of the list entries...
0x49
0x69
0x131

Invariant culture...
0x69
0x49
0x131

Invariant culture, ignore case...
Desktop CLR:

0x49
0x69
0x131

Core CLR:

0x69
0x49
0x131

The current culture is "en-US".
Current culture...
0x69
0x49
0x131

Current culture, ignore case...

Desktop CLR:

0x49
0x69
0x131

Core CLR:

0x69
0x49
0x131

Ordinal...
0x49
0x69
0x131

Ordinal, ignore case...
Desktop CLR:

0x69
0x49
0x131

Core CLR:

0x49
0x69
0x131

Turkish culture, ignore case...
Desktop CLR:

0x131
0x49
0x69

Core CLR:

0x49
0x131
0x69

Expected:
Desktop CLR and Core CLR result should be the same

@davidfowl
Copy link
Member

Probably something to do with how we're configuring the CLR host.

@xqiu
Copy link
Author

xqiu commented Nov 21, 2014

For ease, project.json for VS2015 preview is:

{
    "version": "1.0.0-*",
    "dependencies": {
    },
    "commands": { 
        "run" : "run"
    },
    "frameworks" : {
        "aspnet50" : { },
        "aspnetcore50" : { 
            "dependencies": {
                "System.Console": "4.0.0-beta-22231",
                "System.Globalization": "4.0.10-beta-22231",
                "System.Globalization.Extensions": "4.0.0-beta-22231",
                "System.Collections": "4.0.10-beta-22231",
                "System.Collections.Concurrent": "4.0.10-beta-22231",
                "System.Linq": "4.0.0-beta-22231"
            }
        }
    }
}

@muratg
Copy link
Contributor

muratg commented Dec 5, 2014

Do we need to file this in CoreCLR issue tracking system?

@xqiu
Copy link
Author

xqiu commented Dec 5, 2014

It's internal bug 1017568, which CoreCLR team didn't find problem and believe is our host problem.

@troydai
Copy link
Contributor

troydai commented Mar 5, 2015

This issue still can be repo today.

@troydai troydai added the bug label Mar 5, 2015
@muratg
Copy link
Contributor

muratg commented Mar 9, 2015

@troydai Can you try this with your hacked up code to pass Culture across threads?

/cc: @DamianEdwards

@muratg muratg added this to the 1.0.0-rc1 milestone Mar 9, 2015
@troydai
Copy link
Contributor

troydai commented Mar 11, 2015

Test application:
https://github.com/troydai/dnx-issue600

The full comparison across DNX451, DNXCORE50 and Desktop .Net 4.5.1:


True    Original order
        DNXCORE50:      0x49, 0x69, 0x131
        DNX451:         0x49, 0x69, 0x131
        Desktop:        0x49, 0x69, 0x131
True    InvariantCulture
        DNXCORE50:      0x69, 0x49, 0x131
        DNX451:         0x69, 0x49, 0x131
        Desktop:        0x69, 0x49, 0x131
True    InvariantCultureIgnoreCase
        DNXCORE50:      0x69, 0x49, 0x131
        DNX451:         0x69, 0x49, 0x131
        Desktop:        0x69, 0x49, 0x131
True    CurrentCulture
        DNXCORE50:      0x69, 0x49, 0x131
        DNX451:         0x69, 0x49, 0x131
        Desktop:        0x69, 0x49, 0x131
False   CurrentCultureIgnoreCase
        DNXCORE50:      0x49, 0x69, 0x131
        DNX451:         0x69, 0x49, 0x131
        Desktop:        0x69, 0x49, 0x131
True    Ordinal
        DNXCORE50:      0x49, 0x69, 0x131
        DNX451:         0x49, 0x69, 0x131
        Desktop:        0x49, 0x69, 0x131
False   OrdinalIgnoreCase
        DNXCORE50:      0x49, 0x69, 0x131
        DNX451:         0x69, 0x49, 0x131
        Desktop:        0x49, 0x69, 0x131
False   Culture:tr-TR
        DNXCORE50:      0x49, 0x131, 0x69
        DNX451:         0x131, 0x49, 0x69
        Desktop:        0x49, 0x131, 0x69

*Desktop: A .net 4.5.1 console application not on K stack

@muratg
Copy link
Contributor

muratg commented Mar 11, 2015

@troydai was this with your hack? in other words, does it still fail to the proper comparison with your hack?

@troydai
Copy link
Contributor

troydai commented Mar 11, 2015

It's not hacking. I'm working on the results after apply #953 changes.

@troydai
Copy link
Contributor

troydai commented Mar 20, 2015

Fixed.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants