Fix ScanDriverException serialization for worker

This commit is contained in:
Ben Olden-Cooligan 2019-03-17 15:48:46 -04:00
parent 7f13df5fdf
commit 086bc54d83
15 changed files with 73 additions and 85 deletions

View File

@ -22,5 +22,15 @@ namespace NAPS2.Sdk.Tests.Config
Assert.Single(config2.FormStates);
Assert.Equal("Test", config2.FormStates[0].Name);
}
[Fact]
public void NoNulls()
{
var config = InternalDefaults.GetCommonConfig();
foreach (var prop in typeof(CommonConfig).GetProperties())
{
Assert.NotNull(prop.GetValue(config));
}
}
}
}

View File

@ -10,6 +10,7 @@ using NAPS2.Images;
using NAPS2.Images.Storage;
using NAPS2.ImportExport.Email.Mapi;
using NAPS2.Scan;
using NAPS2.Scan.Exceptions;
using NAPS2.Scan.Twain;
using NAPS2.Worker;
using Xunit;
@ -113,6 +114,27 @@ namespace NAPS2.Sdk.Tests.Worker
}
}
[Fact]
public async Task TwainScanException()
{
var twainWrapper = new TwainWrapperMockScanner
{
Exception = new DeviceException("Test error")
};
using (var channel = Start(twainWrapper))
{
var ex = await Assert.ThrowsAsync<DeviceException>(async () => await channel.Client.TwainScan(
new ScanDevice("test_id", "test_name"),
new ScanProfile(),
new ScanParams(),
IntPtr.Zero,
CancellationToken.None,
(img, path) => { }));
Assert.Contains(nameof(TwainWrapperMockScanner), ex.StackTrace);
Assert.Contains("Test error", ex.Message);
}
}
private ScannedImage CreateScannedImage()
{
return new ScannedImage(new GdiImage(new Bitmap(100, 100)));
@ -122,6 +144,8 @@ namespace NAPS2.Sdk.Tests.Worker
{
public List<ScannedImage> Images { get; set; } = new List<ScannedImage>();
public Exception Exception { get; set; }
public List<ScanDevice> GetDeviceList(TwainImpl twainImpl) => throw new NotSupportedException();
public void Scan(IntPtr dialogParent, ScanDevice scanDevice, ScanProfile scanProfile, ScanParams scanParams, CancellationToken cancelToken, ScannedImageSink sink,
@ -131,6 +155,11 @@ namespace NAPS2.Sdk.Tests.Worker
{
sink.PutImage(img);
}
if (Exception != null)
{
throw Exception;
}
}
}

View File

@ -46,7 +46,7 @@ namespace NAPS2.Config.Experimental
DisableExitConfirmation = false,
SingleInstance = false,
ComponentsPath = "",
OcrTimeoutInSeconds = 10 * 60 * 1000, // 10 minutes
OcrTimeoutInSeconds = 10 * 60, // 10 minutes
EnableOcr = false,
OcrLanguageCode = "",
OcrMode = OcrMode.Default,

View File

@ -5,17 +5,15 @@ using System.Runtime.Serialization;
namespace NAPS2.Scan.Exceptions
{
[Serializable]
public class DeviceException : ScanDriverException
{
protected DeviceException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
public DeviceException(string message)
: base(message)
{
}
public DeviceException()
{
}
}
}

View File

@ -6,14 +6,8 @@ using NAPS2.Lang.Resources;
namespace NAPS2.Scan.Exceptions
{
[Serializable]
public class DeviceNotFoundException : ScanDriverException
{
protected DeviceNotFoundException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
public DeviceNotFoundException()
: base(MiscResources.DeviceNotFound)
{

View File

@ -6,14 +6,8 @@ using NAPS2.Lang.Resources;
namespace NAPS2.Scan.Exceptions
{
[Serializable]
public class DriverNotSupportedException : ScanDriverException
{
protected DriverNotSupportedException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
public DriverNotSupportedException()
: base(MiscResources.DriverNotSupported)
{

View File

@ -6,14 +6,8 @@ using NAPS2.Lang.Resources;
namespace NAPS2.Scan.Exceptions
{
[Serializable]
public class NoDevicesFoundException : ScanDriverException
{
protected NoDevicesFoundException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
public NoDevicesFoundException()
: base(MiscResources.NoDevicesFound)
{

View File

@ -6,14 +6,8 @@ using NAPS2.Lang.Resources;
namespace NAPS2.Scan.Exceptions
{
[Serializable]
public class NoDuplexSupportException : ScanDriverException
{
protected NoDuplexSupportException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
public NoDuplexSupportException()
: base(MiscResources.NoDuplexSupport)
{

View File

@ -6,14 +6,8 @@ using NAPS2.Lang.Resources;
namespace NAPS2.Scan.Exceptions
{
[Serializable]
public class NoFeederSupportException : ScanDriverException
{
protected NoFeederSupportException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
public NoFeederSupportException()
: base(MiscResources.NoFeederSupport)
{

View File

@ -6,14 +6,8 @@ using NAPS2.Lang.Resources;
namespace NAPS2.Scan.Exceptions
{
[Serializable]
public class NoPagesException : ScanDriverException
{
protected NoPagesException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
public NoPagesException()
: base(MiscResources.NoPagesInFeeder)
{

View File

@ -6,16 +6,10 @@ using NAPS2.Lang.Resources;
namespace NAPS2.Scan.Exceptions
{
[Serializable]
public class SaneNotAvailableException : ScanDriverException
{
private const string PACKAGES = "\nsane\nsane-utils";
protected SaneNotAvailableException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
public SaneNotAvailableException() : base(MiscResources.SaneNotAvailable + PACKAGES)
{
}

View File

@ -5,11 +5,9 @@ using System.Runtime.Serialization;
namespace NAPS2.Scan.Exceptions
{
[Serializable]
public abstract class ScanDriverException : Exception
{
protected ScanDriverException(SerializationInfo info, StreamingContext context)
: base(info, context)
protected ScanDriverException()
{
}

View File

@ -6,11 +6,9 @@ using NAPS2.Lang.Resources;
namespace NAPS2.Scan.Exceptions
{
[Serializable]
public class ScanDriverUnknownException : ScanDriverException
{
protected ScanDriverUnknownException(SerializationInfo info, StreamingContext context)
: base(info, context)
public ScanDriverUnknownException()
{
}

View File

@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Xml.Serialization;
using NAPS2.Logging;
using NAPS2.Scan.Exceptions;
using NAPS2.Util;
namespace NAPS2.Worker
@ -12,35 +12,32 @@ namespace NAPS2.Worker
{
public static void HandleErrors(Error error)
{
if (!string.IsNullOrEmpty(error?.Xml))
if (!string.IsNullOrEmpty(error?.Type))
{
var knownExceptionTypes = new Type[] { }; // TODO
var exception = error.Xml.FromXml<Exception>();
exception.PreserveStackTrace();
throw exception;
}
else if (!string.IsNullOrEmpty(error?.Name))
{
throw new Exception($"GRPC endpoint error {error.Name}: {error.Message}");
var exceptionType = Assembly.GetAssembly(typeof(ScanDriverException))
.GetTypes()
.FirstOrDefault(x => x.FullName == error.Type);
if (exceptionType != null)
{
var exception = (Exception)Activator.CreateInstance(exceptionType);
var messageField = typeof(Exception).GetField("_message", BindingFlags.NonPublic | BindingFlags.Instance);
var stackTraceField = typeof(Exception).GetField("_stackTraceString", BindingFlags.NonPublic | BindingFlags.Instance);
messageField?.SetValue(exception, error.Message);
stackTraceField?.SetValue(exception, error.StackTrace);
exception.PreserveStackTrace();
throw exception;
}
throw new Exception($"An error occurred on the gRPC server.\n{error.Type}: {error.Message}\n{error.StackTrace}");
}
}
private static Error ToError(Exception e)
{
var error = new Error();
try
private static Error ToError(Exception e) =>
new Error
{
error.Xml = e.ToXml();
}
catch (Exception serializerEx)
{
Log.ErrorException("Error serializing exception object", serializerEx);
Log.ErrorException("Original exception", e);
}
error.Name = e.GetType().Name;
error.Message = e.Message;
return error;
}
Type = e.GetType().FullName,
Message = e.Message,
StackTrace = e.StackTrace
};
public static Task<TResponse> WrapFunc<TResponse>(Func<TResponse> action, Func<Error, TResponse> error) =>
Task.Run(() =>
@ -77,7 +74,7 @@ namespace NAPS2.Worker
}
catch (Exception e)
{
error(new Error { Xml = e.ToXml() });
error(ToError(e));
}
});
}

View File

@ -12,9 +12,9 @@ service GrpcWorkerService {
}
message Error {
string xml = 1;
string name = 2;
string message = 3;
string type = 1;
string message = 2;
string stackTrace = 3;
}
message InitRequest {