Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include the file path in the exception when configuration loading fails #35183

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ private void Load(bool reload)
}
else
{
var error = new StringBuilder($"The configuration file '{Source.Path}' was not found and is not optional.");
var error = new StringBuilder(SR.Format(SR.Error_FileNotFound, Source.Path));
if (!string.IsNullOrEmpty(file?.PhysicalPath))
{
error.Append($" The physical path is '{file.PhysicalPath}'.");
error.Append(SR.Format(SR.Error_ExpectedPhysicalPath, file.PhysicalPath));
}
HandleException(ExceptionDispatchInfo.Capture(new FileNotFoundException(error.ToString())));
}
Expand All @@ -88,7 +88,8 @@ private void Load(bool reload)
}
catch (Exception e)
{
HandleException(ExceptionDispatchInfo.Capture(e));
var exception = new InvalidDataException(SR.Format(SR.Error_LoadFailed, file.PhysicalPath), e);
HandleException(ExceptionDispatchInfo.Capture(exception));
}
}
}
Expand All @@ -101,6 +102,9 @@ private void Load(bool reload)
/// </summary>
/// <exception cref="FileNotFoundException">If Optional is <c>false</c> on the source and a
/// file does not exist at specified Path.</exception>
/// <exception cref="InvalidDataException">Wrapping any exception thrown by the concrete implementation of the
/// <see cref="Load()"/> method. Use the source <see cref="FileConfigurationSource.OnLoadException"/> callback
/// if you need more control over the exception.</exception>
public override void Load()
{
Load(reload: false);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Expand Down Expand Up @@ -118,9 +118,12 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Error_ExpectedPhysicalPath" xml:space="preserve">
<value>The expected physical path was '{0}'.</value>
<value> The expected physical path is '{0}'.</value>
</data>
<data name="Error_FileNotFound" xml:space="preserve">
<value>The configuration file '{0}' was not found and is not optional.</value>
</data>
<data name="Error_LoadFailed" xml:space="preserve">
<value>Failed to load configuration from file '{0}'.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Extensions.Configuration.Test;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Primitives;
using Moq;
using Xunit;

Expand Down Expand Up @@ -35,14 +33,55 @@ public void ProviderDisposesChangeTokenRegistration()
Assert.Empty(changeToken.Callbacks);
}

[Theory]
[InlineData(@"C:\path\to\configuration.txt")]
[InlineData(@"/path/to/configuration.txt")]
public void ProviderThrowsInvalidDataExceptionWhenLoadFails(string physicalPath)
{
var fileProviderMock = new Mock<IFileProvider>();
fileProviderMock.Setup(fp => fp.Watch(It.IsAny<string>())).Returns(new ConfigurationRootTest.ChangeToken());
fileProviderMock.Setup(fp => fp.GetFileInfo(It.IsAny<string>())).Returns(new FileInfoImpl(physicalPath));

var source = new FileConfigurationSourceImpl
{
FileProvider = fileProviderMock.Object,
ReloadOnChange = true,
};
var exceptionOnLoad = new Exception("An error occured");
var provider = new FileConfigurationProviderImpl(source, exceptionOnLoad);

var exception = Assert.Throws<InvalidDataException>(() => provider.Load());
Assert.Contains($"'{physicalPath}'", exception.Message);
Assert.Equal(exceptionOnLoad, exception.InnerException);
}

public class FileInfoImpl : IFileInfo
{
public FileInfoImpl(string physicalPath) => PhysicalPath = physicalPath;
public Stream CreateReadStream() => new MemoryStream();
public bool Exists => true;
public bool IsDirectory => false;
public DateTimeOffset LastModified => default;
public long Length => default;
public string Name => default;
public string PhysicalPath { get; }
}

public class FileConfigurationProviderImpl : FileConfigurationProvider
{
public FileConfigurationProviderImpl(FileConfigurationSource source)
private readonly Exception _exceptionOnLoad;

public FileConfigurationProviderImpl(FileConfigurationSource source, Exception exceptionOnLoad = null)
: base(source)
{ }
{
_exceptionOnLoad = exceptionOnLoad;
}

public override void Load(Stream stream)
{ }
{
if (_exceptionOnLoad != null)
throw _exceptionOnLoad;
}
}

public class FileConfigurationSourceImpl : FileConfigurationSource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,9 +382,9 @@ public void OnLoadErrorWillBeCalledOnJsonParseError()
.SetFileLoadExceptionHandler(jsonLoadError)
.Build();
}
catch (Exception e)
catch (InvalidDataException e)
{
Assert.Equal(e, jsonError);
Assert.Equal(e.InnerException, jsonError);
}

Assert.NotNull(provider);
Expand All @@ -410,9 +410,9 @@ public void OnLoadErrorWillBeCalledOnXmlParseError()
.SetFileLoadExceptionHandler(loadError)
.Build();
}
catch (Exception e)
catch (InvalidDataException e)
{
Assert.Equal(e, error);
Assert.Equal(e.InnerException, error);
}

Assert.NotNull(provider);
Expand All @@ -439,9 +439,9 @@ public void OnLoadErrorWillBeCalledOnIniLoadError()
.SetFileLoadExceptionHandler(loadError)
.Build();
}
catch (FormatException e)
catch (InvalidDataException e)
{
Assert.Equal(e, error);
Assert.Equal(e.InnerException, error);
}
Assert.NotNull(provider);
}
Expand Down