String comparison with escape chars

Ask general questions here.
Darwin
Posts: 26
Joined: Tue Jul 25, 2017 9:00 pm

String comparison with escape chars

Post by Darwin » Thu Mar 22, 2018 6:17 pm

I am trying to do a file comparison by calculating the MD5 hash of two files and comparing the hashes as strings. This works just fine in my sample project in Visual Studio, but when I copy the code over to Ranorex the string comparisons continually fail.

I am declaring constants from known files using the "\u" escape characters:

Code: Select all

        const string source16MBFile1Hash = "N^´ûÈZ÷~¸‰a\u001c?Â/\u0005";  // 16MByte_XOR_data_01.bin
        const string source16MBFile2Hash = "6”Á½ADõuº@ëZVÎ\u0006Ô";       // 16MByte_XOR_data_02.bin
Then finding and comparing the hash of a particular file to the known source file:

Code: Select all

        public void VerifySourceAndDeviceHashes(string sourceFileHash)
        {
            string readFile = tmpFolder + GetNewestFile(tmpFolder);

            string deviceHash = CheckMd5(readFile);
        	
            if (sourceFileHash != deviceHash)
            {
            	Report.Failure(string.Format("Hashes did not match.  Expected: {0}  Actual:  {1}", sourceFileHash, deviceHash));
            }
            else
            {
            	Report.Log(ReportLevel.Info, string.Format("Hashes matched. {0} == {1}", sourceFileHash, deviceHash));
            }
        }
MD5 hash function:

Code: Select all

        private string CheckMd5(string filename)
        {
            using (var md5 = MD5.Create())
            {
                using (var stream = File.OpenRead(filename))
                {
                    return Encoding.Default.GetString(md5.ComputeHash(stream));
                }
            }
        }
Ranorex logs these errors, as strings are "close" but obviously not close enough:

Code: Select all

    Hashes did not match. Expected: 6”Á½ADõuº@ëZVÎ\u0006Ô Actual: 6”Á½ADõuº@ëZVÎ�Ô
Are there some encoding options pre-set in Ranorex I need to manipulate? As mentioned, this code worked just fine in my VS trial project.

Darwin
Posts: 26
Joined: Tue Jul 25, 2017 9:00 pm

Re: String comparison with escape chars

Post by Darwin » Thu Mar 22, 2018 10:43 pm

OK--So I guess the real question is, "How can I pass a string value with escape chars embedded and intact?"

I ask this because I am not using the constants in my example when actually running the test in Ranorex. I was trying to pass the values declared in those constants, but I expect that Ranorex is replacing the escape chars with literals, e.g.: "\u100c" becomes "\\u100c" so the backslash is interpreted as a literal character and not the beginning of an escape sequence.

I messed with the code to use the constant value and it passes, so I expect I'll either need to re-write the code to handle this in Ranorex, unless there is a way to tell Ranorex, "Use this actual value--don't parse it and interpret it literally!"

ahoisl
Certified Professional
Certified Professional
Posts: 125
Joined: Fri Sep 07, 2007 8:16 am

Re: String comparison with escape chars

Post by ahoisl » Fri Mar 23, 2018 8:46 am

I'm sorry, but I could not reproduce your problem. This should have nothing to do with Ranorex as all you use is plain C# code to compare the file hashes. The only Ranorex API you use is the reporting, but after you actually checked the hashes.
And the report does not escape string characters, simply because it would not know that this is an escaped character. The compiler already transforms escape sequences to real unicode strings.

Try to use Console.WriteLine and see what the output is. I guess it either has something to do with your file already being stored as Unicode or with the escape code. Did you try to use the "\x" character escape instead?

Regards,
Alex
Ranorex Team

Darwin
Posts: 26
Joined: Tue Jul 25, 2017 9:00 pm

Re: String comparison with escape chars

Post by Darwin » Fri Mar 23, 2018 5:49 pm

Alex--

Thanks--I'm not surprised you couldn't repro, as I did a poor job explaining the problem. I was trying to leave my function intact and pass a string value into it via data binding, e.g.:

Code: Select all

public void VerifySourceAndDeviceHashes(string sourceFileHash)
And using the Data Binding UI (image).

What I've done instead is change the parameter to an int, use a switch clause, and assign the now-internal sourceFileHash variable to a constant value. That's my workaround for now.
Attachments
Ranorex.png
Ranorex.png (2.9 KiB) Viewed 406 times

ahoisl
Certified Professional
Certified Professional
Posts: 125
Joined: Fri Sep 07, 2007 8:16 am

Re: String comparison with escape chars

Post by ahoisl » Fri Mar 23, 2018 8:15 pm

Ahhh, yes, the data binding dialog does indeed escape all characters, i.e. it treats the text as is not allowing any escape characters. You can either put in the Unicode string right away, use code, or change your method to use hexadecimal hash strings :)

Regards,
Alex
Ranorex Team

Darwin
Posts: 26
Joined: Tue Jul 25, 2017 9:00 pm

Re: String comparison with escape chars

Post by Darwin » Fri Mar 23, 2018 8:28 pm

Alex--

Thanks--using the hex hash strings is a good idea. I want to keep the function open and flexible for re-use with other test cases, and that'd be a better implementation than a monster switch clause.

Darwin
Posts: 26
Joined: Tue Jul 25, 2017 9:00 pm

Re: String comparison with escape chars

Post by Darwin » Mon Mar 26, 2018 5:25 pm

I've converted this all to the hex hash string (Unicode had the same problems as UTF). I did notice in my original version however that any logging with those string values containing escape sequences/unprintable chars breaks JUnit/XML logging. I've entered this issue in the Bug Reports forum.

https://www.ranorex.com/forum/escape-ch ... 11993.html

FWIW, the hex hash string version is now:

Code: Select all

        public void VerifySourceAndDeviceHashes(string expectedHash)
        {       	
            string readFile = tmpFolder + GetNewestFile(tmpFolder);

            string actualHash = CheckMd5(readFile);
            
            if (expectedHash != actualHash)
            {
            	Report.Failure(string.Format("Hashes did not match.  Expected: {0}  Actual:  {1}", expectedHash, actualHash));
            }
            else
            {
            	Report.Log(ReportLevel.Info, string.Format("Hashes matched. {0} == {1}", expectedHash, actualHash));
            }
        }

        /// <summary>
        /// Returns the MD5 hash for the given file.
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        private string CheckMd5(string filename)
        {
            using (var md5 = MD5.Create())
            {
                using (var stream = File.OpenRead(filename))
                {
                    byte[] hashChars = md5.ComputeHash(stream);

                    return ToHex(hashChars, true);
                }
            }
        }

        /// <summary>
        /// Converts a byte array into a string of hexadecimal values
        /// </summary>
        /// <param name="bytes">Byte array of values, e.g.: {78, 94, 180, 251, 200, 90, 247, 126, 184, 137, 97, 28, 63, 194, 47, 5}</param>
        /// <param name="upperCase">If true, use A-F; if false, a-f.</param>
        /// <returns>String of hex values, e.g.:"4E5EB4FBC85AF77EB889611C3FC22F05"</returns>
        private string ToHex(byte[] bytes, bool upperCase)
        {
            StringBuilder result = new StringBuilder(bytes.Length * 2);

            for (int i = 0; i < bytes.Length; i++)
                result.Append(bytes[i].ToString(upperCase ? "X2" : "x2"));

            return result.ToString();
        }
I can now pass in values like "4E5EB4FBC85AF77EB889611C3FC22F05" in the Data Binding UI and run my tests.

Thanks again--

ahoisl
Certified Professional
Certified Professional
Posts: 125
Joined: Fri Sep 07, 2007 8:16 am

Re: String comparison with escape chars

Post by ahoisl » Wed Mar 28, 2018 8:51 am

Thanks for posting that problem!

Regards,
Alex
Ranorex Team