Skip to content

Commit 906f02a

Browse files
authored
add tests (#6)
* add tests, but they fail. * add download and unzip steps * try curl * dont build for now * 7zip * config setup * try path * turn on build * checkout current branch * checkout pr code * log * typo * rel path * ugh * interopolate * release * test release * mark failure * ignore failre * review comments * review comments * review comments
1 parent 9d23bdf commit 906f02a

9 files changed

+560
-6
lines changed

.github/workflows/build.yml

+16-3
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,41 @@ jobs:
99
uses: actions/checkout@v4
1010
with:
1111
path: DSIronPython3
12-
repository: DynamoDS/DSIronPython3
12+
ref: ${{ github.ref }}
13+
1314
- name: Setup nuget
1415
uses: nuget/[email protected]
1516
- name: Setup msbuild
1617
uses: microsoft/[email protected]
1718
- name: Nuget Restore DSIronPython3 solution
19+
if: ${{ true }}
1820
run: nuget restore ${{ github.workspace }}\DSIronPython3\IronPython3Extension.sln
1921
- name: Build DSIronPython3 with MSBuild
22+
if: ${{ true }}
2023
run: |
2124
Write-Output "***Continue with the build, Good luck developer!***"
22-
msbuild ${{ github.workspace }}\DSIronPython3\IronPython3Extension.sln
25+
msbuild ${{ github.workspace }}\DSIronPython3\IronPython3Extension.sln -p:Configuration=Release
2326
- name: Look for package
27+
if: ${{ true }}
2428
run: |
2529
Write-Output "***Locating iron python package!***"
2630
if (Test-Path -Path "${{ github.workspace }}\DSIronPython3\package_output\DSIronPython3\bin\python3eval.dll") {
2731
Write-Output "python node dll exists!"
2832
} else {
2933
Write-Error "python node dll was not found!"
3034
}
35+
- name: Get DynamoRuntime from s3
36+
run: |
37+
curl -o DynamoRuntime.zip https://dyn-builds-data.s3-us-west-2.amazonaws.com/DynamoCoreRuntime3.0.2.zip
38+
ls
39+
- name: Extract DynamoRuntime
40+
run: |
41+
7z x DynamoRuntime.zip -o${{ github.workspace }}\DSIronPython3\IronPython3Tests\bin\Release\net8.0\DynamoRuntime
42+
43+
3144
- name: Run test with the dotnet CLI
3245
run: |
33-
dotnet test ${{ github.workspace }}\DSIronPython3 --logger "trx;LogFileName=results.trx" --results-directory ${{ github.workspace }}\DSIronPython3\TestResults
46+
dotnet test ${{ github.workspace }}\DSIronPython3 -p:Configuration=Release --filter "TestCategory!=Failure" --logger "trx;LogFileName=results.trx" --results-directory ${{ github.workspace }}\DSIronPython3\TestResults
3447
- name: Upload build artifact
3548
uses: actions/[email protected]
3649
with:

IronPython3Extension.sln

+7-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ VisualStudioVersion = 17.5.33424.131
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IronPython3Extension", "IronPython3Extension\IronPython3Extension.csproj", "{7A44B553-ED7E-4C01-A91A-70C7AD5897A8}"
77
EndProject
8-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "python3eval", "python3eval\python3eval.csproj", "{2B256D7E-4864-4086-A481-6E5B24CBA95E}"
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "python3eval", "python3eval\python3eval.csproj", "{2B256D7E-4864-4086-A481-6E5B24CBA95E}"
9+
EndProject
10+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IronPython3Tests", "IronPython3Tests\IronPython3Tests.csproj", "{CD76A408-05CF-45E6-A508-6A6BA6A95E75}"
911
EndProject
1012
Global
1113
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -21,6 +23,10 @@ Global
2123
{2B256D7E-4864-4086-A481-6E5B24CBA95E}.Debug|Any CPU.Build.0 = Debug|Any CPU
2224
{2B256D7E-4864-4086-A481-6E5B24CBA95E}.Release|Any CPU.ActiveCfg = Release|Any CPU
2325
{2B256D7E-4864-4086-A481-6E5B24CBA95E}.Release|Any CPU.Build.0 = Release|Any CPU
26+
{CD76A408-05CF-45E6-A508-6A6BA6A95E75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27+
{CD76A408-05CF-45E6-A508-6A6BA6A95E75}.Debug|Any CPU.Build.0 = Debug|Any CPU
28+
{CD76A408-05CF-45E6-A508-6A6BA6A95E75}.Release|Any CPU.ActiveCfg = Release|Any CPU
29+
{CD76A408-05CF-45E6-A508-6A6BA6A95E75}.Release|Any CPU.Build.0 = Release|Any CPU
2430
EndGlobalSection
2531
GlobalSection(SolutionProperties) = preSolution
2632
HideSolutionNode = FALSE

IronPython3Extension/IronPython3Extension.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net6.0</TargetFramework>
4+
<TargetFramework>net8.0</TargetFramework>
55
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
66
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
77
<OutputPath>$(SolutionDir)\package_output\DSIronPython3\bin\</OutputPath>
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
8+
<IsPackable>false</IsPackable>
9+
<IsTestProject>true</IsTestProject>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="DynamoVisualProgramming.Tests" Version="3.1.0-beta3874" />
14+
<PackageReference Include="coverlet.collector" Version="6.0.0" />
15+
<PackageReference Include="System.Configuration.ConfigurationManager" Version="8.0.0" />
16+
</ItemGroup>
17+
18+
<ItemGroup>
19+
<ProjectReference Include="..\python3eval\python3eval.csproj" />
20+
</ItemGroup>
21+
22+
<ItemGroup>
23+
<None Update="TestServices.dll.config">
24+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
25+
</None>
26+
</ItemGroup>
27+
28+
</Project>

IronPython3Tests/Setup.cs

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Configuration;
4+
using System.Globalization;
5+
using System.IO;
6+
using System.Reflection;
7+
using NUnit.Framework;
8+
9+
10+
[SetUpFixture]
11+
public class Setup
12+
{
13+
private string moduleRootFolder;
14+
List<string> resolutionPaths;
15+
16+
[OneTimeSetUp]
17+
public void RunBeforeAllTests()
18+
{
19+
var thisDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
20+
var configPath = Path.Combine(thisDir, "TestServices.dll.config");
21+
22+
// Adjust the config file map because the config file
23+
// might not always be in the same directory as the dll.
24+
var map = new ExeConfigurationFileMap { ExeConfigFilename = configPath };
25+
var config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
26+
27+
var element = config.AppSettings.Settings["DynamoBasePath"];
28+
moduleRootFolder = element?.Value ?? string.Empty;
29+
30+
if (string.IsNullOrEmpty(moduleRootFolder))
31+
{
32+
throw new Exception($"Missing DynamoBasePath in TestServices.dll.config. Please set the DynamoBasePath to a valid Dynamo bin folder. DynamoBasePath is set to {moduleRootFolder}");
33+
}
34+
else if (!File.Exists(Path.Combine(moduleRootFolder, "DynamoCore.dll")))
35+
{
36+
throw new Exception($"Invalid DynamoBasePath in TestServices.dll.config. Please set the DynamoBasePath to a valid Dynamo bin folder. DynamoBasePath is set to {moduleRootFolder}");
37+
}
38+
39+
resolutionPaths = new List<string>
40+
{
41+
// Search for nodes
42+
Path.Combine(moduleRootFolder, "nodes")
43+
};
44+
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; ;
45+
}
46+
47+
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
48+
{
49+
try
50+
{
51+
var targetAssemblyName = new AssemblyName(args.Name).Name + ".dll";
52+
53+
// First check the core path
54+
string assemblyPath = Path.Combine(moduleRootFolder, targetAssemblyName);
55+
if (File.Exists(assemblyPath))
56+
{
57+
return Assembly.LoadFrom(assemblyPath);
58+
}
59+
60+
// Then check all additional resolution paths
61+
foreach (var resolutionPath in resolutionPaths)
62+
{
63+
assemblyPath = Path.Combine(resolutionPath, targetAssemblyName);
64+
if (File.Exists(assemblyPath))
65+
{
66+
return Assembly.LoadFrom(assemblyPath);
67+
}
68+
}
69+
70+
return null;
71+
}
72+
catch (Exception ex)
73+
{
74+
throw new Exception(string.Format("There location of the assembly, " +
75+
"{0} could not be resolved for loading.", args.Name), ex);
76+
}
77+
}
78+
79+
[OneTimeTearDown]
80+
public void RunAfterAllTests()
81+
{
82+
AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve;
83+
}
84+
}
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<configuration>
3+
<appSettings>
4+
<add key="DynamoBasePath" value=".\DynamoRuntime"/>
5+
<add key="RequestedLibraryVersion2" value=""/>
6+
</appSettings>
7+
</configuration>

IronPython3Tests/pythonEvalTests.cs

+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
using Dynamo;
2+
using NUnit.Framework;
3+
using System.Collections;
4+
5+
6+
namespace IronPython3Tests
7+
{
8+
public class PythonEvalTests : UnitTestBase
9+
{
10+
public delegate object PythonEvaluatorDelegate(string code, IList bindingNames, IList bindingValues);
11+
12+
public IEnumerable<PythonEvaluatorDelegate> Evaluators = new List<PythonEvaluatorDelegate> {
13+
IronPython3.Evaluator.IronPython3Evaluator.EvaluateIronPythonScript,
14+
};
15+
16+
[Test]
17+
[Category("UnitTests")]
18+
public void EvaluatorWorks()
19+
{
20+
foreach (var pythonEvaluator in Evaluators)
21+
{
22+
var empty = new ArrayList();
23+
var output = pythonEvaluator("OUT = 0", empty, empty);
24+
Assert.AreEqual(0, output);
25+
}
26+
}
27+
28+
[Test]
29+
[Category("UnitTests")]
30+
public void BindingsWork()
31+
{
32+
const string expected = "Hi!";
33+
34+
var names = new ArrayList { "test" };
35+
var vals = new ArrayList { expected };
36+
37+
foreach (var pythonEvaluator in Evaluators)
38+
{
39+
var output = pythonEvaluator(
40+
"OUT = test",
41+
names,
42+
vals
43+
);
44+
45+
Assert.AreEqual(expected, output);
46+
}
47+
}
48+
49+
[Test]
50+
[Category("UnitTests")]
51+
public void DataMarshaling_Output()
52+
{
53+
var marshaler = IronPython3.Evaluator.IronPython3Evaluator.OutputMarshaler;
54+
marshaler.RegisterMarshaler((string s) => s.Length);
55+
56+
const string script = "OUT = ['', ' ', ' ']";
57+
58+
object output = IronPython3.Evaluator.IronPython3Evaluator.EvaluateIronPythonScript(
59+
script,
60+
new ArrayList(),
61+
new ArrayList());
62+
63+
Assert.AreEqual(new[] { 0, 1, 2 }, output);
64+
65+
marshaler.UnregisterMarshalerOfType<string>();
66+
}
67+
68+
[Test]
69+
[Category("UnitTests")]
70+
public void DataMarshaling_Input()
71+
{
72+
var marshaler = IronPython3.Evaluator.IronPython3Evaluator.InputMarshaler;
73+
marshaler.RegisterMarshaler((string s) => s.Length);
74+
75+
const string script = "OUT = sum(IN)";
76+
77+
object output = IronPython3.Evaluator.IronPython3Evaluator.EvaluateIronPythonScript(
78+
script,
79+
new ArrayList { "IN" },
80+
new ArrayList { new ArrayList { " ", " " } });
81+
82+
Assert.AreEqual(3, output);
83+
84+
marshaler.UnregisterMarshalerOfType<string>();
85+
}
86+
87+
88+
[Test]
89+
public void SliceOperator_Output()
90+
{
91+
var names = new ArrayList { "indx" };
92+
var vals = new ArrayList { 3 };
93+
94+
foreach (var pythonEvaluator in Evaluators)
95+
{
96+
var output = pythonEvaluator(
97+
"OUT = [1,2,3,4,5,6,7][indx:indx+2]",
98+
names,
99+
vals);
100+
101+
var expected = new ArrayList { 4, 5 };
102+
103+
Assert.AreEqual(expected, output);
104+
}
105+
}
106+
107+
[Test]
108+
public void IronPythonGivesCorrectErrorLineNumberAndLoadsStdLib()
109+
{
110+
var code = @"
111+
from xml.dom.minidom import parseString
112+
my_xml = parseString('invalid XML!')
113+
";
114+
try
115+
{
116+
IronPython3.Evaluator.IronPython3Evaluator.EvaluateIronPythonScript(code, new ArrayList(), new ArrayList());
117+
Assert.Fail("An exception was expected");
118+
}
119+
catch (Exception exc)
120+
{
121+
StringAssert.StartsWith(@"Traceback (most recent call last):
122+
File ""<string>"", line 3, in <module>", exc.Message);
123+
StringAssert.EndsWith("Data at the root level is invalid. Line 1, position 1.", exc.Message);
124+
}
125+
}
126+
127+
[Test]
128+
public void NonListIterablesCanBeOutput()
129+
{
130+
var code = @"
131+
s = { 'hello' }
132+
fs = frozenset({ 'world' })
133+
d = { 'one': 1 }
134+
dk = d.keys()
135+
dv = d.values()
136+
di = d.items()
137+
138+
OUT = s,fs,dk,dv,di
139+
";
140+
var expected = new ArrayList
141+
{
142+
new ArrayList { "hello" },
143+
new ArrayList { "world" },
144+
new ArrayList { "one" },
145+
new ArrayList { 1 },
146+
new ArrayList { new ArrayList { "one", 1 } }
147+
};
148+
var empty = new ArrayList();
149+
foreach (var pythonEvaluator in Evaluators)
150+
{
151+
var output = pythonEvaluator(code, empty, empty);
152+
Assert.AreEqual(expected, output);
153+
}
154+
}
155+
}
156+
}

0 commit comments

Comments
 (0)