Bug 23994 - Inconsistent Exceptions thrown when passing null as the source file of a copy invocation
Summary: Inconsistent Exceptions thrown when passing null as the source file of a copy...
Status: VERIFIED INVALID
Alias: None
Product: iOS
Classification: Xamarin
Component: XI runtime ()
Version: XI 8.2.0
Hardware: Macintosh Mac OS
: Normal normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2014-10-22 12:34 UTC by Stephen Rawlins
Modified: 2015-01-13 12:24 UTC (History)
6 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
VERIFIED INVALID

Description Stephen Rawlins 2014-10-22 12:34:47 UTC
As part of our Unit-testing, we explicitly try invoking a file copy method but passing a null string as the source file (the target file does not matter). 

We were expecting to get an exception (perhaps System.ArgumentNullException or a not-found exception), but we have discovered that Xamarin.iOS throws System.ArgumentException, whereas Xamarin.Android System.ArgumentNullException

This seems inconsistent, given that Xamarin should be mimicking a standard, consistent .NET behavior.


try {
  Copy(null, Device.DataPath);
}


            catch (System.IO.DirectoryNotFoundException)
            {
                // thrown by NUnit and other runners
                Assert.Pass();
            }
            catch (System.IO.IOException)
            {
                // thrown when run by VS2013 Test Runner plugin
                Assert.Pass();
            }
            catch (System.ArgumentNullException)
            {
                // thrown by Android
                //TODO: Submit a bug to Xamarin
                Assert.Pass();            
            }
            catch (System.ArgumentException)
            {
                // thrown by iOS
                //TODO: Submit a bug to Xamarin
                Assert.Pass();            
            }
Comment 1 Rolf Bjarne Kvinge [MSFT] 2014-10-22 16:28:02 UTC
Are you referring to this Copy method: http://msdn.microsoft.com/en-us/library/c6cfw35a(v=vs.110).aspx ?
Comment 2 Stephen Rawlins 2014-10-23 11:46:54 UTC
Rolf,
Yes, I am referring to System.IO.File.Copy (on Windows), just as you have stated.  Specifically:


File.Copy(sourcefilename, destinationfilename, true);


On Android and iOS, this standard System.IO library call binds to different underlying code, and we are looking to Xamarin for consistent exception handling.
Comment 3 Rolf Bjarne Kvinge [MSFT] 2014-10-24 06:13:53 UTC
This test case:

	public class Application {
	    static void Main (string[] args)
		{
			try {
				System.IO.File.Copy (null, "not null");
			} catch (Exception ex) {
				Console.WriteLine (ex.GetType ().FullName);
			}
	    }
	}

prints:

    System.ArgumentNullException

which is what you're expecting (but not experiencing) from what I understand. It's also the documented behavior on MSDN.

Could you attach a complete test project, since obviously something strange is going on for you?
Comment 4 Stephen Rawlins 2014-10-24 16:13:07 UTC
Rolf,
Thanks for the test-case code.
Did you try running your test case on both iOS and Android?

When running our UnitTests on iOS (using Xamarin.iOS), the Copy test throws System.ArgumentException:

2014-10-24 13:41:20.510 TestRunnerTouch[14800:584709] 	[PASS] CopyFileNullDestination
2014-10-24 13:41:20.510 TestRunnerTouch[14800:584709] >>>>>>>CopyFileNullSource begins
>>>>>>>CopyFileNullSource begins
2014-10-24 13:41:20.511 TestRunnerTouch[14800:584709] >>>>>>>Before Copy
>>>>>>>Before Copy
2014-10-24 13:41:20.511 TestRunnerTouch[14800:584709] >>>>>>>System.ArgumentException
>>>>>>>System.ArgumentException
2014-10-24 13:41:20.557 TestRunnerTouch[14800:584709] 	[PASS] CopyFileNullSource : System.ArgumentException


When running the same tests on Android (using Xamarin.Android), the same Copy throws System.NullReferenceException:

>>>>>>>CopyFileNullSource begins
10-24 15:08:33.217 I/mono-stdout(24894): >>>>>>>CopyFileNullSource begins
[0:] >>>>>>>CopyFileNullSource begins
[0:] 
>>>>>>>Before Copy
[0:] >>>>>>>Before Copy
10-24 15:08:33.258 I/mono-stdout(24894): >>>>>>>Before Copy
	[FAIL] CopyFileNullSource : Did not catch any of the expected Exception. Exception thrown was System.NullReferenceException
10-24
Comment 5 Stephen Rawlins 2014-10-24 16:35:36 UTC
It seems that native Windows (whether from stand-alone NUnit runner or Visual Studio plugin TestRunner) throws System.IO.DirectoryNotFoundException:

***** UnitTests.FileSystem.BasicFileTests.CopyFileNullSource
>>>>>>>CopyFileNullSource begins
>>>>>>>System.IO.DirectoryNotFoundException

but iOS throws System.ArgumentException and Android throw System.NullReferenceException.  None of which are the desired System.ArgumentNullException

Here is the test, with some Debug statements added:

        [Test]
        public void CopyFileNullSource()
        {
            Debug.WriteLine(">>>>>>>CopyFileNullSource begins");
            try
            {
                Debug.WriteLine(">>>>>>>Before Copy");
                Device.File.Copy(null, Device.DataPath);
                Debug.WriteLine(">>>>>>>After Copy");
            }
            catch (System.IO.DirectoryNotFoundException)
            {
                // thrown by NUnit and other runners
                Debug.WriteLine(">>>>>>>System.IO.DirectoryNotFoundException");
                Assert.Pass("System.IO.DirectoryNotFoundException");
            }
            catch (System.IO.IOException)
            {
                // thrown when run by in Windows, stand-alone NUnit or VS2013 plug-in TestRunner
                Debug.WriteLine(">>>>>>>System.IO.IOException");
                Assert.Pass("System.IO.IOException");
            }
            catch (System.ArgumentNullException)
            {
                // not thrown!
                Debug.WriteLine(">>>>>>>System.ArgumentNullException");
                Assert.Pass("System.ArgumentNullException");            
            }
            catch (System.ArgumentException)
            {
                // thrown by iOS
                Debug.WriteLine(">>>>>>>System.ArgumentException");
                Assert.Pass("System.ArgumentException");            
            }
            catch (Exception e)
            {
                Assert.Fail("Did not catch any of the expected Exception. Exception thrown was " + e.GetType());
            }

            Assert.Fail("No exception thrown");
        }
Comment 6 Rolf Bjarne Kvinge [MSFT] 2014-10-24 17:07:47 UTC
(In reply to comment #5)
>                 Device.File.Copy(null, Device.DataPath);

This is not System.IO.File.Copy, it's something else.

In any case please attach a complete test project we can try out, otherwise we'd just be guessing.
Comment 7 Stephen Rawlins 2014-11-07 11:35:59 UTC
I'm marking this ticket RESOLVED (INVALID).

My testing now shows that both Xamarin.Android and Xamarin.iOS return:

    System.ArgumentNullException

as desired.

So there must be some other reason that I am seeing an discrepancy in the UnitTests.  I'll file a different bugzilla report if I find anything that would suggest Xamarin is responsible.
Comment 8 Mohit Kheterpal 2015-01-13 12:24:26 UTC
As per comment 7, this issue is invalid.

So, I am closing this issue by marking it as Verified Invalid.