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

fix tests #15159

Merged
merged 13 commits into from
Apr 25, 2024
2 changes: 1 addition & 1 deletion src/DynamoCore/Models/DynamoModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@ protected DynamoModel(IStartConfiguration config)
//run process startup/reading on another thread so we don't block dynamo startup.
//if we end up needing to control aspects of dynamo model or view startup that we can't make
//event based/async then just run this on main thread - ie get rid of the Task.Run()
var mainThreadSyncContext = new SynchronizationContext();
var mainThreadSyncContext = SynchronizationContext.Current ?? new SynchronizationContext();
Task.Run(() =>
{
try
Expand Down
6 changes: 3 additions & 3 deletions src/DynamoCore/Scheduler/AsyncTaskExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
Expand Down Expand Up @@ -27,7 +27,7 @@ public static IDisposable Then(this AsyncTask task, AsyncTaskCompletedHandler ac
/// <returns>An IDisposable representing the event subscription</returns>
public static IDisposable ThenPost(this AsyncTask task, AsyncTaskCompletedHandler action, SynchronizationContext context = null)
{
if (context == null) context = new SynchronizationContext(); // uses the default
if (context == null) context = SynchronizationContext.Current ?? new SynchronizationContext(); // uses the current or a default
return task.Then((t) => context.Post((_) => action(task), null));
aparajit-pratap marked this conversation as resolved.
Show resolved Hide resolved
}

Expand All @@ -38,7 +38,7 @@ public static IDisposable ThenPost(this AsyncTask task, AsyncTaskCompletedHandle
/// <returns>An IDisposable representing the event subscription</returns>
public static IDisposable ThenSend(this AsyncTask task, AsyncTaskCompletedHandler action, SynchronizationContext context = null)
{
if (context == null) context = new SynchronizationContext(); // uses the default
if (context == null) context = SynchronizationContext.Current ?? new SynchronizationContext(); // uses the current or a default
return task.Then((t) => context.Send((_) => action(task), null));
}

Expand Down
4 changes: 3 additions & 1 deletion src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,9 @@ private void UnsubscribeDispatcherEvents()
}
#endregion

private void InitializeAutomationSettings(string commandFilePath)
// InitializeAutomationSettings initializes the Dynamo automationSettings object.
// This method is meant to be accessed only within this class and within tests.
internal void InitializeAutomationSettings(string commandFilePath)
{
if (String.IsNullOrEmpty(commandFilePath) || !File.Exists(commandFilePath))
commandFilePath = null;
Expand Down
2 changes: 1 addition & 1 deletion src/DynamoUtilities/DynamoFeatureFlagsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ internal void CacheAllFlags()
try
{
AllFlagsCache = JsonConvert.DeserializeObject<Dictionary<string, object>>(dataFromCLI);
//invoke the flags retrieved event on the sync context which should be the main ui thread.
// Invoke the flags retrieved event on the sync context which should be the main ui thread (if in Dynamo with UI) or the default SyncContext (if in headless mode).
syncContext?.Send((_) =>
{
FlagsRetrieved?.Invoke();
Expand Down
7 changes: 1 addition & 6 deletions test/DynamoCoreTests/UnitsOfMeasureTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ internal class UnitsOfMeasureTests : UnitTestBase
[SetUp]
public override void Setup()
{
base.Setup();
Display.PrecisionFormat = "f4";
}

Expand Down Expand Up @@ -758,12 +759,6 @@ public void CanMapOverUnits()
}
internal class ForgeUnitsTests : UnitTestBase
{
[SetUp]
public override void Setup()
{

}

const string milimeters = "autodesk.unit.unit:millimeters";
const string meters = "autodesk.unit.unit:meters";

Expand Down
27 changes: 26 additions & 1 deletion test/DynamoCoreWpfTests/DynamoTestUIBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using Dynamo.Configuration;
Expand All @@ -15,7 +16,6 @@
using Dynamo.Nodes;
using Dynamo.Scheduler;
using Dynamo.ViewModels;
using Dynamo.Wpf.Utilities;
using DynamoCoreWpfTests.Utility;
using DynamoShapeManager;
using DynamoUtilities;
Expand All @@ -32,6 +32,11 @@ public class DynamoTestUIBase
protected DynamoView View { get; set; }
protected DynamoModel Model { get; set; }

// Use this flag to skip trying to execute all the dispatched operations during the test lifetime.
// This flag should only be used very sparingly
protected bool SkipDispatcherFlush = false;
protected int DispatcherOpsCounter = 0;

protected string ExecutingDirectory
{
get { return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); }
Expand Down Expand Up @@ -84,6 +89,11 @@ public virtual void Start()
View.Show();

SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What will the current thread be typically in which this test fixture is set up?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We run all our tests in a single thread (UI thread).
We set the current syncContext the same way WPF would set when running the application normally (DispatcherSynchronizationContext)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's surprising to me that if the tests are running in the UI thread, we have to do this explicitly. Perhaps this is a subtle difference between a main WPF app and a WPF test.


if (!SkipDispatcherFlush)
{
Dispatcher.CurrentDispatcher.Hooks.OperationPosted += Hooks_OperationPosted;
}
}

protected static void RaiseLoadedEvent(FrameworkElement element)
Expand All @@ -96,6 +106,14 @@ protected static void RaiseLoadedEvent(FrameworkElement element)
eventMethod.Invoke(element, new object[] { args });
}

private void Hooks_OperationPosted(object sender, DispatcherHookEventArgs e)
{
e.Operation.Task.ContinueWith((t) => {
Interlocked.Decrement(ref DispatcherOpsCounter);
}, TaskScheduler.Default);
Interlocked.Increment(ref DispatcherOpsCounter);
}

/// <summary>
/// Derived test classes can override this method to provide different configurations.
/// </summary>
Expand All @@ -114,6 +132,13 @@ protected virtual DynamoModel.IStartConfiguration CreateStartConfiguration(IPath
[TearDown]
public void Exit()
{
if (!SkipDispatcherFlush)
{
Dispatcher.CurrentDispatcher.Hooks.OperationPosted -= Hooks_OperationPosted;

DispatcherUtil.DoEventsLoop(() => DispatcherOpsCounter == 0);
}

//Ensure that we leave the workspace marked as
//not having changes.
ViewModel.HomeSpace.HasUnsavedChanges = false;
Expand Down
2 changes: 2 additions & 0 deletions test/DynamoCoreWpfTests/DynamoViewModelUnitTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class DynamoViewModelUnitTest : DSEvaluationUnitTestBase
{
protected DynamoViewModel ViewModel;
protected Preloader preloader;
protected string CommandFilePath;

protected override DynamoModel GetModel()
{
Expand Down Expand Up @@ -131,6 +132,7 @@ protected void StartDynamo()
new DynamoViewModel.StartConfiguration()
{
DynamoModel = model,
CommandFilePath = CommandFilePath,
Watch3DViewModel = new DefaultWatch3DViewModel(null, watch3DViewParams)
});

Expand Down
26 changes: 9 additions & 17 deletions test/DynamoCoreWpfTests/PreviewBubbleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,9 @@ public void PreviewBubble_ListMargin()
nodeView.PreviewControl.RaiseEvent(new RoutedEventArgs(FrameworkElement.LoadedEvent));

// Fire transition on dynamo main ui thread.
View.Dispatcher.Invoke(() =>
{
nodeView.PreviewControl.BindToDataSource();
nodeView.PreviewControl.TransitionToState(Dynamo.UI.Controls.PreviewControl.State.Condensed);
nodeView.PreviewControl.TransitionToState(Dynamo.UI.Controls.PreviewControl.State.Expanded);
});
nodeView.PreviewControl.BindToDataSource();
nodeView.PreviewControl.TransitionToState(Dynamo.UI.Controls.PreviewControl.State.Condensed);
nodeView.PreviewControl.TransitionToState(Dynamo.UI.Controls.PreviewControl.State.Expanded);

DispatcherUtil.DoEvents();
var watchTree = nodeView.PreviewControl.ChildOfType<WatchTree>();
Expand All @@ -124,12 +121,9 @@ public void PreviewBubble_NumberMargin()
nodeView.PreviewControl.RaiseEvent(new RoutedEventArgs(FrameworkElement.LoadedEvent));

// Fire transition on dynamo main ui thread.
View.Dispatcher.Invoke(() =>
{
nodeView.PreviewControl.BindToDataSource();
nodeView.PreviewControl.TransitionToState(Dynamo.UI.Controls.PreviewControl.State.Condensed);
nodeView.PreviewControl.TransitionToState(Dynamo.UI.Controls.PreviewControl.State.Expanded);
});
nodeView.PreviewControl.BindToDataSource();
nodeView.PreviewControl.TransitionToState(Dynamo.UI.Controls.PreviewControl.State.Condensed);
nodeView.PreviewControl.TransitionToState(Dynamo.UI.Controls.PreviewControl.State.Expanded);

DispatcherUtil.DoEvents();
var watchTree = nodeView.PreviewControl.ChildOfType<WatchTree>();
Expand All @@ -145,11 +139,9 @@ public void PreviewBubble_CloseWhenFocusInCodeBlock()
var nodeView = NodeViewWithGuid("1382aaf9-9432-4cf0-86ae-c586d311767e");
nodeView.PreviewControl.RaiseEvent(new RoutedEventArgs(FrameworkElement.LoadedEvent));

View.Dispatcher.Invoke(() =>
{
nodeView.PreviewControl.BindToDataSource();
nodeView.PreviewControl.TransitionToState(Dynamo.UI.Controls.PreviewControl.State.Condensed);
});
nodeView.PreviewControl.BindToDataSource();
nodeView.PreviewControl.TransitionToState(Dynamo.UI.Controls.PreviewControl.State.Condensed);

DispatcherUtil.DoEvents();
nodeView.ChildOfType<ICSharpCode.AvalonEdit.Editing.TextArea>().Focus();

Expand Down
Loading
Loading