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

Tests for CPython3 Engine as well as for IronPython. #10631

Merged
merged 26 commits into from
May 14, 2020

Conversation

reddyashish
Copy link
Contributor

@reddyashish reddyashish commented May 5, 2020

Purpose

This PR is in reference to the task: https://jira.autodesk.com/browse/DYN-2190
This adds more tests to the DynamoPythonTests solution and executes the current tests with both the IronPython and CPython3 Engine.

There is one failing test related to the Integer marshaling.
Update on the test:
Integers of type int64 and lower are now being marshaled but BigIntegers are failing as PythonNet doesn't have a class like the PyInt or PyLong. This will need some more work and will file a task for it.

Declarations

Check these if you believe they are true

  • The codebase is in a better state after this PR
  • Is documented according to the standards
  • The level of testing this PR includes is appropriate
  • User facing strings, if any, are extracted into *.resx files
  • All tests pass using the self-service CI.
  • Snapshot of UI changes, if any.
  • Changes to the API follow Semantic Versioning and are documented in the API Changes document.

Reviewers

@DynamoDS/dynamo

aparajit-pratap and others added 11 commits April 28, 2020 16:15
This fixes a problem where existing custom nodes in the home workspace
became unresolved after a package that contained binaries was loaded.

The cause of the problem was that the compiled function was not
available at the time of the execution after a VM reset. Now the data
is registered on package load, by queueing it in
pendingCustomNodeSyncData. This results in a CompileCustomNodeAsyncTask
being scheduled before the update of the home workspace graph takes
place.
* Add a test for the CrashPromptArgs class

* Update DynamoCoreTests.csproj

* Added NotificationObject tests

* Updated the test, NotificationObject coverage at 100%

* Changed some access modifiers

* Added coverage for Updates/BinaryVersion

* Added comments and fixed names

* Revert "Added comments and fixed names"

This reverts commit 42cd024.

* Revert "Added coverage for Updates/BinaryVersion"

This reverts commit 679deca.

* Increased coverage in CrashPromptArgs

* Added some Core coverage
… Part (DynamoDS#10612)

* DYN-2560 - Increase the code coverage: DynamoCore/Models Folder

I started adding just one test method TestOnRequestDispatcherBeginInvoke() for testing the DynamoModelEvents class.

* DYN-2560 - Adding test cases for DynamoModelEvents

Adding test cases for DynamoModelEvents

* DYN-2560 - Adding test cases for DynamoModelEvents

I added all the test cases for the all events  in the DynamoModelEvent class, i just need to fix the last 6 of them.

* DYN-2560 - Adding test cases for DynamoModelEventsArgs

I added several test cases for the classes inside the DynamoModelEventsArgs.cs file.

     ZoomEventArgs
     TaskDialogEventArgs
     EvaluationCompletedEventArgs
     DynamoModelUpdateArgs
     FunctionNamePromptEventArgs
     PresetsNamePromptEventArgs
     ViewOperationEventArgs
     PointEventArgs
     WorkspaceEventArgs
     ModelEventArgs

* DYN-2560 - Code Review Comments

Based in the comment done by Aaron in the GitHub pull request, I added more description comments for the method TestTaskDialogEventArgs() and also I added comments for a local function

* DYN-2560 - Code Review Comments 2

There was a spelling error in two methods for the word "Internally", then I fixed this error in the two places.
* Cherrypick

* Comments

* Add unit test

* Comments
When the runtime table are built there is an implicit assumption that
the code block ids are consecutive. However, that is not always the
case, as the deletion of a procedure causes the deletion of its child
code blocks, which may generate gaps in the id numbering.

In order to make the code resiliant to these gaps, the runtime tables
are sized based on the largest code block id, rather than in the amount
of code blocks.
The check for the specific assemblies tbb.dll and tbbmalloc.dll is
generalized to a full file list validation of detected ASM locations.
This way, Dynamo is guarded against any incomplete/unusual ASM binary
folders that other applications might include.

The lists of files for each version were taken from LibG. They cannot
be reused from LibG without involving major changes in the preloader,
so the lists should be kept in sync as new major release of ASM occur.
* (1) Null reference bug fix from SQ dashboard
* Add support for debug modes
* Add a test for the CrashPromptArgs class

* Update DynamoCoreTests.csproj

* Added NotificationObject tests

* Updated the test, NotificationObject coverage at 100%

* Changed some access modifiers

* Added coverage for Updates/BinaryVersion

* Added comments and fixed names

* Added asserts for happy path, changed namespace and deleted a console function

* Removed using

* Revert "Removed using"

This reverts commit 022823d.

* Removed a change that should not be there

* Added coverage for Updates folder
@reddyashish reddyashish added the WIP label May 5, 2020
mjkkirschner and others added 4 commits May 5, 2020 14:23
…serialization tests. (DynamoDS#10624)

* reduce number of serialization tests by factor 3~

* reduce wpf json serialization tests
A code block node calling an instance method in its static form would
make Dynamo crash if the instance was not provided. An example of this
would be calling 'Curve.Patch();'.

The cause of the issue was that the default argument was ultimately
tried to be interpreted as a pointer. By avoiding that wrong conversion
the engine is now able to surface the real problem as a human-readable
warning.
* Cherrypick Python3 changes

* Cleanup

* Use Debug Modes

* CleanUp

* Rename Function

* Clean Up

* Do not use anouymous function as handler

* Revert newer language change
src/Libraries/PythonNodeModels/PythonNode.cs Outdated Show resolved Hide resolved

foreach (var pythonEngine in pythonEngineVersionsList)
{
UpdateEnginePropertyForPythonNode(pynode, pythonEngine);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the workspace in an unsaved state at this stage due to changes to engine property?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The workspace doesn't have any changes as we are just modifying the Engine property on the node.

Copy link
Member

Choose a reason for hiding this comment

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

I think that means it does have unsaved changes- the engine property is a serializable value of the node right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But this flag ViewModel.Model.CurrentWorkspace.HasUnsavedChanges is false.

Copy link
Member

Choose a reason for hiding this comment

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

that sounds like a bug!?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The python node object is also marked as unmodified. Should it be marked as modified if the workspace is expected to have any changes?

Copy link
Contributor Author

@reddyashish reddyashish May 8, 2020

Choose a reason for hiding this comment

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

I will look more into this.

Copy link
Member

Choose a reason for hiding this comment

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

it makes sense to me, that if the engine is changed the node should be marked as modified as this should re-execute the graph, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added the comment above to address this.

mmisol and others added 2 commits May 7, 2020 12:12
When an array is passed to the dot operation, it needs to get an item
to determine the actual class being processed. This was done in
ArrayUtils.GetFirstNonArrayStackValue, but the function only checked
the first item of the array and its descendants. This caused the dot
operation to failed when passed an array that contained an empty array
as its first item.

In order to fix the problem, the function was changed to check for
non-array items in the entire array. The function should stop as soon
as the first non-array item is found.
@reddyashish reddyashish changed the title [WIP] Tests for CPython3 Engine as well as for IronPython. Tests for CPython3 Engine as well as for IronPython. May 8, 2020
@reddyashish reddyashish removed the WIP label May 8, 2020
@@ -100,6 +100,7 @@
<ProjectReference Include="..\DSIronPython\DSIronPython.csproj">
<Project>{9eef4f42-6b3b-4358-9a8a-c2701539a822}</Project>
<Name>DSIronPython</Name>
<Private>False</Private>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This will not copy the DSIronPython.dll into the nodes folder as we have that binary in the debug folder. Before this, it was being copied into 2 locations.

Copy link
Collaborator

@mmisol mmisol left a comment

Choose a reason for hiding this comment

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

Left a few comments.

I guess my main concern is what to do with the failing test. If it feels it's going to take long to fix, we can probably mark it as failure and track as a separate task.

@@ -33,6 +37,7 @@ public abstract class PythonNodeBase : VariableInputNode
protected PythonNodeBase(IEnumerable<PortModel> inPorts, IEnumerable<PortModel> outPorts) : base(inPorts, outPorts)
{
ArgumentLacing = LacingStrategy.Disabled;
pythonEngineVersionsList = Enum.GetValues(typeof(PythonEngineVersion)).Cast<PythonEngineVersion>();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please notice we are re-initializing a static field each time a Python node is created.

Also, adding a field to our code just to be used in the tests is not something we should do if we can avoid it. In this case it seems easy to avoid, we just need to a helper method in our test class.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Initially, I was using a static list in the tests to get the values. But the tests were failing because it couldn't find the PythonNodeModels.dll (the enum is defined in here) at runtime. May be the static field was the problem. Getting the list of values inside a function worked. So changed it back. Thanks @mmisol.

var pythonTokens = dynObj["Nodes"].Where(t => t.Value<string>("NodeType") == "PythonScriptNode").Select(t => t);
Assert.IsNotNull(pythonTokens);
Assert.IsTrue(pythonTokens.Any(t => t.Value<string>("Engine") == PythonEngineVersion.IronPython2.ToString()));
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

How about if you changed the value to CPython3 before saving? This would serve to check that the property can serialize both values properly.

Copy link
Contributor Author

@reddyashish reddyashish May 8, 2020

Choose a reason for hiding this comment

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

This test was added by Aaron to check serialization and deserialization of the Engine property on a global level. There is another test PythonNodeEnginePropertyChangeTest that is added to assert the python node values for both the engines.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I saw that test but it's not quite the same thing. My point regarding this suggestion is that it could catch a bug on serialization where the Engine of a python node would always be set to IronPython2. Not saying that's a bug we have or that it is likely to ever appear, but I just thought it would make the test more interesting to change the engine before serializing.

}

[Test]
// This is failing for CPython3 Engine.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we mark this as failing and track as a follow-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.

Marked it as failure.

@reddyashish reddyashish added the PTAL Please Take A Look 👀 label May 8, 2020
Copy link
Collaborator

@mmisol mmisol left a comment

Choose a reason for hiding this comment

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

Looks good to me. Please remember to create a bug to track the test failure

var pythonTokens = dynObj["Nodes"].Where(t => t.Value<string>("NodeType") == "PythonScriptNode").Select(t => t);
Assert.IsNotNull(pythonTokens);
Assert.IsTrue(pythonTokens.Any(t => t.Value<string>("Engine") == PythonEngineVersion.IronPython2.ToString()));
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I saw that test but it's not quite the same thing. My point regarding this suggestion is that it could catch a bug on serialization where the Engine of a python node would always be set to IronPython2. Not saying that's a bug we have or that it is likely to ever appear, but I just thought it would make the test more interesting to change the engine before serializing.

@@ -49,7 +51,8 @@ public PythonEngineVersion Engine
if (engine != value)
{
engine = value;
RaisePropertyChanged("Engine");
RaisePropertyChanged(nameof(Engine));
OnNodeModified();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mjkkirschner @aparajit-pratap this will mark the node as modified when the engine property is modified. Also, the workspace will have unsaved changes.

"cb037a9debd54ce79a4007b6ea11de25",
"a9bb1b12fbbd4aa19299f0d30c9f99b2",
"b6bd3049034f488a9bed0373f05fd021"
"845d532f-df87-4d93-9f2e-d66509413ea6",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@QilongTang This test was not asserting the truth values as it doesn't match the GUID pattern. Had to insert the '-' character.

Copy link
Contributor

Choose a reason for hiding this comment

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

@reddyashish Thanks for fixing! Make sense

}

[Test]
public void TestWorkspaceWithMultiplePythonEngines()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test will verify that workspace has unsaved changes when the PythonEngine property is modified on a node. Also checks that python nodes with different Python Engines in a single workspace works.

@@ -82,14 +85,16 @@ protected override string GetInputTooltip(int index)
var vals = additionalBindings.Select(x => x.Item2).ToList();
vals.Add(AstFactory.BuildExprList(inputAstNodes));

Func<string, IList, IList, object> pythonEvaluatorMethod;
Copy link
Contributor

Choose a reason for hiding this comment

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

This will create conflict with the DSPython3 branch, just FYI

else if(PyLong.IsLongType(pyObj))
{
return PyLong.AsLong(pyObj).ToInt64();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

@reddyashish is this the fix for the int to double param method resolution issue?

Copy link
Member

@mjkkirschner mjkkirschner May 11, 2020

Choose a reason for hiding this comment

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

curious as well as I thought that was filed as a separate bug.

Copy link
Member

Choose a reason for hiding this comment

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

also ... isn't a Long the same as Int64?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not for double. This is the case for int64 bit integers. Before this only int32 were working.
I will be filing the issue for BigInteger marshaling.

The deadlock was happening only when multiple PythonEngine's are initialized on a thread from 2 different test fixtures in the same run.
The main difference is calling this function PythonEngine.BeginAllowThreads().
Also we do not want to initialze the python engine if it is already initialized.
{
int amt = Math.Min(bindingNames.Count, bindingValues.Count);
PythonEngine.Initialize();
PythonEngine.BeginAllowThreads();
Copy link
Member

Choose a reason for hiding this comment

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

@reddyashish - you will need to tell me what is happening here 😉 - did one of your new tests introduce a deadlock?
@Dewb FYI

Copy link
Member

Choose a reason for hiding this comment

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

Just saw your comment, in what situations (which test jobs) are multiple test fixtures creating multiple python engines in the same process?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think the explanation is here https://github.com/pythonnet/pythonnet/wiki/Threading

The Python interpreter only actually runs single-threaded. You can create additional threads, but only one thread at a time has the Global Interpreter Lock (GIL), and only that thread can run.

So that would mean only one thread should call PythonNet at a time. Not sure what test was failing though.

Copy link
Contributor Author

@reddyashish reddyashish May 13, 2020

Choose a reason for hiding this comment

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

Sorry guys, was waiting for the self-serve. Tested it locally. I wrote the explanation below.

Copy link
Contributor Author

@reddyashish reddyashish May 13, 2020

Choose a reason for hiding this comment

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

It isn't happening with a single test but when the PythonEngine is initialized from 2 different test fixtures. They are PythonEditTests and IronPythonTests(will probably need to change this name as we have tests for both engines in here).

@reddyashish
Copy link
Contributor Author

reddyashish commented May 13, 2020

Team, the Nunit tests were running into a deadlock situation for DynamoPythonTests.dll. This was happening specifically when the function CPythonEvalutor.EvaluatePythonScript was called from 2 different test fixtures in a single test run. They were passing separately and also when all the tests are in a single test fixture.
To avoid this, we have to call PythonEngine.BeginAllowThreads() and use thread locks during python evaluation. We will also not be initializing the PythonEngine if it is already initialized from the previous tests.

For more information, please take a look at pythonnet/pythonnet#109.

@reddyashish reddyashish requested a review from Dewb May 13, 2020 16:41
@reddyashish
Copy link
Contributor Author

@reddyashish
Copy link
Contributor Author

Merging this.

@reddyashish reddyashish merged commit 734b16c into DynamoDS:DSCPython3 May 14, 2020
@reddyashish reddyashish deleted the Python3 branch November 23, 2022 07:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PTAL Please Take A Look 👀
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants