WPF coded UI test randomly fails with weird ArgumentException - c#

I have coded UI tests in WPF application and they occasionally fail with the following exception:
Message: Test method MyMethodNameGoesHere threw exception:
System.ArgumentException: Parameter is not valid.
and StackTrace:
at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, PixelFormat format)
at System.Drawing.Bitmap..ctor(Int32 width, Int32 height)
at Microsoft.VisualStudio.TestTools.UITesting.LoggerUtility.GetDesktopImage()
at Microsoft.VisualStudio.TestTools.UITesting.LoggerUtility.CaptureScreenShotAndDrawBounds(Int32 x, Int32 y, Int32 width, Int32 height, Int32 borderWidth, Boolean isActualControlBounds)
at Microsoft.VisualStudio.TestTools.UITest.Extension.LoggerUtilities.CaptureScreenShotAndDrawBounds(Rectangle bounds, Int32 borderWidth, Boolean isActualControlBounds)
at Microsoft.VisualStudio.TestTools.UITesting.Playback.CaptureScreenShot(UITestControl control)
at Microsoft.VisualStudio.TestTools.UITesting.Playback.GetUITestControlString(UITestControl control)
at Microsoft.VisualStudio.TestTools.UITesting.Playback.MapControlNotFoundException(COMException ex, IPlaybackContext context)
at Microsoft.VisualStudio.TestTools.UITesting.Playback.MapAndThrowComException(COMException innerException, IPlaybackContext context)
at Microsoft.VisualStudio.TestTools.UITesting.Playback.MapAndThrowException(Exception exception, IPlaybackContext context)
at Microsoft.VisualStudio.TestTools.UITesting.Playback.MapAndThrowException(Exception exception, String queryId)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.FindFirstDescendant(String queryId, Int32 maxDepth, Int32& timeLeft)
at Microsoft.VisualStudio.TestTools.UITesting.SearchHelper.GetElement(Boolean useCache, ISearchArgument searchArg)
at Microsoft.VisualStudio.TestTools.UITesting.SearchHelper.Search(ISearchArgument searchArg)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.FindInternal()
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.<Find>b__175_0()
at Microsoft.VisualStudio.TestTools.UITesting.CodedUITestMethodInvoker.InvokeMethod[T](Func`1 function, UITestControl control, Boolean firePlaybackErrorEvent, Boolean logAsAction)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.Find()
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.GetPropertyPrivate(String propertyName)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.GetPropertyOfType[T](String propertyName)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.get_Exists()
at MyProjectNamespace.UITests.TestButtonExists() in E:\...\UITests.cs:line 177
Any code that tries to access properties of UITestControl like Exists, Checked or Selected throws it. For example:
WpfButton button = UIControlBuilder<WpfButton>.Builder()
.Parent(MainPane)
.AutomationID(MyButtonId)
.Build();
// ...
Assert.IsTrue(button.Exists);
Interestingly, this issue happens randomly, but with some pattern. If I run tests one by one, then they work well. If I run many tests in row, then after some time one test fails and then all consequent tests fail too. I thought that it could be a memory-related issue (leakage or out of memory), but I definitely have lots of memory available and processes don't seem to consume much of it.
From my investigation UI test framework catches an exception in FindFirstDescendant and tries to capture a screenshot to report this exception, but fails to do this too:
// decompiled UI test framework's UITestControl.cs code
internal UITestControl FindFirstDescendant(string queryId, int maxDepth, ref int timeLeft)
{
// ...
try
{
element = this.ScreenElement.FindScreenElement(queryId, maxDepth);
}
catch (Exception ex) // catches exception here
{
// but this method does also throw exception, because of a bug:
Microsoft.VisualStudio.TestTools.UITesting.Playback.MapAndThrowException(ex, queryId);
throw;
}
}
Even more interesting that this is a very generic error which happens in the constructor of .NET's Bitmap (invalid width or height parameter?).
Because of this Bitmap issue I can't get the original exception, so I can't understand what happens. Playback.CaptureScreenShot is marked with compiler warning suppression attribute, which clearly specifies that this method shouldn't throw any exceptions.
Is this a bug in UI testing framework?
One more interesting observation. It creates screenshots in my test directory, but the application's window is highlighted incorrectly on screenshots. This is how it looks like. Red is my display setup, blue is where the main window actually is, green is how WPF highlights on test result screenshot:
The distance of green narrow line and blue narrow line for corners are equal, so for me it seems like like it takes the application's window's offset within single main display, but then it tries to take a screenshot by applying the offset to all displays.
Can it be a cause of a bug (like going out of display's bounds) or is it just another thing?

Since it looked like a bug, I have asked the same question on DeveloperCommunity.
It seems like the multi-screen is just unsupported:
Thanks for investigation on this issue. looks like you are running coded ui test with multi screen. This is actually an unsupported scenario.
Also Coded UI test is in deprecation path. Check https://learn.microsoft.com/en-us/visualstudio/test/use-ui-automation-to-test-your-code?view=vs-2017
We suggest moving to Selenium or Appium with WinAppDriver as the case may be

Related

Index was outside the bounds of the array in calling WCF API

I have developed a web application with ASP.net(C#, .Net Framework 4.0) in some part of the application I am calling an API to get some information. I noticed that some of the calls to API are failed and I got this error:
Index was outside the bounds of the array.
when I checked the stack trace I saw this :
at System.Collections.Generic.Dictionary2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary2.set_Item(TKey key, TValue
value)
at Navitaire.Ncl.Validation.ValidationManager.getValidationAttributes(MemberInfo mi, Boolean& skip)
at Navitaire.Ncl.Validation.ValidationManager.validate(Object declaringObject, Object value, MemberInfo mi, List1 results)
at Navitaire.Ncl.Validation.ValidationManager.Validate(Object obj)
at Navitaire.Ncl.ServiceModel.ParameterValidationInspector.BeforeCall(String operationName, Object[] inputs)
at Navitaire.Ncl.ServiceModel.Remoting.BoilerplateSinkBase.InvokeBeforeCallInspectors(StateData stateData, RemotingMessage& message)
at Navitaire.Ncl.ServiceModel.Remoting.BoilerplateServerSink.ProcessMessage(IServerChannelSinkStacksinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, IMessage& responseMsg, ITransportHeaders&
responseHeaders, Stream& responseStream)
at System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, IMessage& responseMsg, ITransportHeaders&
responseHeaders, Stream& responseStream)
I put a break point on the catch exception part, so every time that I got the error, application will stop and I can read the exception. I noticed that if in this moment I call the API again (move the cursor to the API call line) it works fine. so it means there is no problem with parameter that I am passing to the API.
I tried to run the application on three different environments with totally different network and different internet connection, but still I got the same error.
Can you please someone help me on this case?
Thanks
I suspect this is a problem with the API, rather than your code, especially if it works the second time you make the same call.
I believe the API is doing something with an internal dictionary, that doesn't quite get set up correctly the first time you call it, but by the second time, it has been and works "correctly".
Are you able to view / have access to the code for the API method your calling?
If so, you are best running that in debug alongside your application, placing a breakpoint on the entry to that method and stepping over the lines within it to see what it is doing and why it may be breaking.
If it's your API, or you're allowed to share the code of this method and you can't find the error yourself, please post up the code of the API method and I'll help you find what the cause could be.
If you are not able to view the code, I would suggest contacting the producer of the API if it's a private one, or if it's an open source API, share the link and provide a code sample of what your code looks like (showing how you make the API call) and we can help diagnose it.
I checked with the API developer and I found that there was some thing wrong on their side after they fixed the bug I did not get any error anymore.

Windows Forms Threads are losing their culture

We have a .net 3.5 multi-threaded windows forms application. Is is launching 4-5 background workers/ async calls to retrieve data. About 1 in 10 times, one of the threads throws the following error. Sometimes the error is a null exception instead but the same exact call stack. We have tracked the issue down to the thread somehow losing its CultureInfo. Anyone else ran into this?
System.Threading.SynchronizationLockException: Object synchronization method was called from an unsynchronized block of code.
at System.Globalization.CultureTableRecord.GetCultureTableRecord(String name, Boolean useUserOverride)
at System.Globalization.CultureTableRecord.GetCultureTableRecord(Int32 cultureId, Boolean useUserOverride)
at System.Globalization.CultureInfo..ctor(Int32 culture, Boolean useUserOverride)
at System.Globalization.CultureInfo.GetCultureByLCIDOrName(Int32 preferLCID, String fallbackToString)
at System.Globalization.CultureInfo.InitUserDefaultUICulture()
at System.Globalization.CultureInfo.get_UserDefaultUICulture()
at System.Threading.Thread.get_CurrentUICulture()
at System.Resources.ResourceManager.GetString(String name, CultureInfo culture)
at System.Environment.ResourceHelper.GetResourceStringCode(Object userDataIn)
at System.Environment.GetResourceFromDefault(String key)
at System.Diagnostics.StackTrace.ToString(TraceFormat traceFormat)
at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
at System.IO.StreamWriter.Init(Stream stream, Encoding encoding, Int32 bufferSize)
at System.IO.StreamWriter..ctor(Stream stream, Encoding encoding, Int32 bufferSize)
at System.Web.Services.Protocols.SoapHttpClientProtocol.GetWriterForMessage(SoapClientMessage message, Int32 bufferSize)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Serialize(SoapClientMessage message)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
Try playing with default culture for entire domain using CultureInfo.DefaultThreadCurrentCulture and/or CultureInfo.DefaultThreadCurrentUICulture and see if that helps. All in all, you'll be able to ensure whether it's related to thread's culture
UPD: that specific exception may be thrown when using sync methods like lock, Monitor, etc on value types, calls to sync methods will box value, creating new one every time. I doubt it could be such serios bug in framework.
Can you check your synchronization code?
UPD2: ok, let's try to debug.
First off, turn on break on every exception thrown
Next, enable .NET Framework debugging that will help you to
locate an error
After that, there is a high chance for a workaround/solution for you problem
From just looking at the call stack, this appears to be a framework bug (of sorts). It seems that the StreamWriter constructor is performing a non-thread-safe operation (accessing GetCultureTableRecord) through a complex series of calls. My recommendation would be to serialize your calls to the StreamWriter constructor:
// Put this somewhere convenient
public static Object swConstructorLock = new Object();
then, when you create your StreamWriters:
// Lock this constructor because it does something that isnt thread-safe as per http://stackoverflow.com/questions/16113366/windows-forms-threads-are-losing-their-culture
StreamWriter myStreamWriter;
lock (swConstructorLock) {
myStreamWriter = new StreamWriter(theStreamToWrite);
}
I found that CultureInfo.ClearCachedData was being called on every web request :/ Removing that fixed the issue. There seems that Culture still needs some sort of lock since thread A calls ClearCachedData and thread B requests the data and it throws a null exception.
I got this exception (once, out of a blue), also in a .NET 3.5 app:
System.Threading.SynchronizationLockException: Object synchronization method was called from an unsynchronized block of code.
at System.Globalization.CultureTableRecord.GetCultureTableRecord(String name, Boolean useUserOverride)
at System.Globalization.CultureTableRecord.GetCultureTableRecord(Int32 cultureId, Boolean useUserOverride)
at System.Globalization.CultureInfo..ctor(Int32 culture, Boolean useUserOverride)
at System.Globalization.CultureInfo.GetCultureByLCIDOrName(Int32 preferLCID, String fallbackToString)
at System.Globalization.CultureInfo.InitUserDefaultCulture()
at System.Globalization.CultureInfo.get_UserDefaultCulture()
at System.Threading.Thread.get_CurrentCulture()
at System.Globalization.DateTimeFormatInfo.get_CurrentInfo()
at System.DateTime.ToString(String format)
This happened in a locked section, but the lock was not a value type.

Exception on Application Closing

I developed a WPF Application where I have problems when closing the application.
Only on Windows 2003 PCs, the application throws the following exception on closing. But it does not seem to be thrown from my code, because I can't get a callstack.
That's why I can't post any further details.
Do you have a clue where I can start digging into it?
System.InvalidOperationException was unhandled
Message=Handle is not initialized.
Source=mscorlib
StackTrace:
at System.WeakReference.set_Target(Object value)
at System.Windows.Threading.Dispatcher.FromThread(Thread thread)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.IntDestroyWindow(HandleRef hWnd)
at MS.Win32.HwndWrapper.DestroyWindow(Object args)
at MS.Win32.HwndWrapper.Dispose(Boolean disposing, Boolean isHwndBeingDestroyed)
at MS.Win32.HwndWrapper.Finalize()
InnerException:
Thanks for your ideas.
EDIT
I found out which lines of code produces the failure. But how can I fix it?
It's the following line of code:
try
{
return DesignerProperties.GetIsInDesignMode(new DependencyObject());
}
catch (Exception)
{
return true;
}
I'm using this to check if the code runs in the designer. But on closing this code fails, although I catched the exception.
Any other ideas to check the designmode?
Thanks for your help.
To answer my own question ...
I could solve the issue by implementing a backing field for the IsInDesignMode Property. The backing field is now going to bet set within the constructor of the ViewModel, instead of my prior solution which checked the DesignMode on every method call.
That means, that even within the Dispose Method it can be checked if the application is/was running in DesignMode.

Marshal.ThrowExceptionForHR throws a NotSupportedException

im using the following pattern for translating win32 exceptions into .NET exceptions.
var result = A_KERNEL32_PINVOKE_CALL();
if (result == 0)
{
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
For completeness the pinvoke call is one of the following: LoadLibrary, GetProcAddress, SetWindowsHookEx.
This works well most of the time, throwing exceptions like this one:
System.ArgumentException: Argument out of range.
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
But sometimes I get the following exception:
System.NotSupportedException: This Stream does not support seek operations.
at System.Net.ConnectStream.get_Position()
at System.Net.WebClient.WebClientWriteStream.get_Position()
at System.Drawing.UnsafeNativeMethods.ComStreamFromDataStream.Seek(Int64 offset, Int32 origin)
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
I can't think of a reason for this exception. Please note that the stack trace doesn't start with ThrowExceptionForHRInternal like the first exception. Hence I think this might be a exception of the ThrowExceptionForHR method itself.
EDIT: Please note that I'm not calling any Stream methods directly. However the code is executed in a thread pool thread, so there might be other code in the same thread using Stream methods.
Any suggestions how to solve this issue?
UPDATE: I just found out, that the stack trace
at System.Net.ConnectStream.get_Position()
at System.Net.WebClient.WebClientWriteStream.get_Position()
at System.Drawing.UnsafeNativeMethods.ComStreamFromDataStream.Seek(Int64 offset, Int32 origin)
belongs to a call to Image.Save(Stream, Format). There a the NotSupportedException is caught. These code peaces are completely independant, but maybe they are executed on the same thread pool thread.
So why does this exception influence my code in another method?
By now I think, that I misused the Marshal.ThrowExceptionForHR() method. I suppose that it's not intended to be used with a Win32 call. My interpretation of the behavior is, that the function uses context information of the current thread to gather more details about the exception. See this blog for a similar problem.
In my case the issue can be solved by creating my own ThrowExceptionForWin32ErrorCode(errorCode) method.
Please keep answering, if you got a better solution.
I don't know why ThrowExceptionForHRInternal tries to manipulate some stream.
While call stack looks strange, consider not passing stream directly from Web response to drawing functions which seem to cause exception in your case but copy data to memory stream first. This will likely allow you to see what original problem is (as ThrowExceptionForHRInternal will no longer fail trying to manipulate a stream).

Catching an Exception across treeview.Nodes.Add / treeview_AfterSelect event boundary

There is a place in my WinForms program that throws a MyOwnException.
void CodeThatThrowsMyOwnException()
{
...
throw new MyOwnException("Deep Inside");
...
}
Further up the stack, there is a simple try/catch block
try
{
CodeThatThrowsMyOwnException();
}
catch (MyOwnException moe)
{
MessageBox.Show("Hit this point in the code! Hurray!");
}
MessageBox.Show("Later, alligator.");
On a colleague's computer (running VS 2008 SP1 like me) the dialog box shows up. On my computer, it never catches the exception nor shows the dialog box. When I place a breakpoint deep inside the code (CodeThatThrowsMyOwnException) on the line that throws the Exception, it hits the breakpoint on the line. If I press F5 (Debug > Run) it skips passed my catch block and displays the "Later, alligator" message.
Actually pasting the "void CodeThatThrowsMyOwnException() { throw new MyOwnException("Shallow"); }" code into my code (instead of calling my real code) and literally calling "CodeThatThrowsMyOwnException();" in the try block does however get show the message in the catch block.
As far as I can tell, I am not creating any threads and I have looked for try {} catch {} blocks that catch all exceptions but cannot find any in the involved projects (and if they were in there, why would this catch block still work on my colleague's machine?)
Strangely enough running my code by double clicking the executable gives me an unhandled exception on my machine and the same on my colleague's machine. This is a clue that led me to try the following:
When I place a breakpoint at the throw MyOwnException("Deep Inside") line deep inside my code, the call stack contains a line "[External Code]" between my exception handler and the place where I call 'throw MyOwnException("Deep Inside")'. If I put a try/catch MyOwnException block further away from the throw (but on this side of the [External Code] I can still catch the exception, anywhere I place the try catch block (around relevant parts of the function chain):
try
{
CodeChain(...);
}
catch (DrawException de)
{
MessageBox.Show("Hurray!"); // being executed, but only on the 'throw' side of the [External Code] part of the call stack
}
However, when I step outside (below on the stack) the [External Code], the exception does not fire. This is unexpected:
try
{
treeview.Nodes.Add(treeNode); // triggers the aforementioned chain of code with MyOwnException thrown
}
catch (DrawException de) // no matter what I do, this will not handle my cursed MyOwnException
{
MessageBox.Show("Hurray!"); // not being executed
}
This is the heart of my problem: I can't move my catch up the call stack because I need to run lots of tests (see below).
I have a sort of hypothesis, which is that his debugger is magically lifting the exception across thread boundaries (or across external code, i.e. Windows GUI events) in his debugger, whereas in the other three situations (my debugger (without the 64 bit extensions) and also when either machine runs the EXE from windows explorer the exception) the exception is truly unhandled on that thread.
So how do I catch this exception? Re-engineer my whole system to avoid using treeview.AfterSelect? Clearly I don't understand the limitations of exceptions.
Potential problem?
I have a delegate in there to keep my system modular and reusable. Can exceptions be thrown "through" a delegate, across module boundaries?
What I'm trying to accomplish (Testing Harness) and why I need Exceptions
I'm using this in an automated test harness. I need to fix some really tough logical/algorithmic bugs in a complicated GUI system by replaying action scripts (text files) that find these exceptional circumstances and narrow the problem down. (There is probably no good workaround to this in my program, in terms of rewriting or refactoring the design: I need to catch these Exceptions in this QA phase, fix the bugs (tough algorithmic special cases) before I ship so I don't subject my users to such buggy software. It's not like I'm using exceptions for exotic control flow for for fun (cf. Int32.Parse).)
The treeview_AfterSelect is going to be called most of the time by what you're referring to as [External Code]. These will be the result of the user selecting a node or even when the form is loading and you're adding nodes (which I suspect might be happening on your unhandled exception).
If your AfterSelect handler is going to throw exceptions for some reason, you cannot rely on your calling code to handle those exceptions. Otherwise, any other way that AfterSelect gets called could result in an unhandled exception.

Categories

Resources