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

[mono] iOS Test runner #34976

Merged
merged 15 commits into from
Apr 17, 2020
Merged
6 changes: 6 additions & 0 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
"commands": [
"reportgenerator"
]
},
"microsoft.dotnet.xharness.cli": {
"version": "1.0.0-prerelease.20214.1",
"commands": [
"xharness"
]
}
}
}
4 changes: 4 additions & 0 deletions eng/Version.Details.xml
Original file line number Diff line number Diff line change
Expand Up @@ -170,5 +170,9 @@
<Uri>https://github.com/mono/linker</Uri>
<Sha>8caef57d1f3bc7a188e5dd26d43a2d34151223f9</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.XHarness.Tests.Runners" Version="1.0.0-prerelease.20214.2">
<Uri>https://github.com/dotnet/xharness</Uri>
<Sha>b5bfc4fcd431ab1fd560bdea7642c7998e30f24d</Sha>
</Dependency>
</ToolsetDependencies>
</Dependencies>
1 change: 1 addition & 0 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
<SystemDataSqlClientVersion>4.8.0</SystemDataSqlClientVersion>
<!-- Testing -->
<MicrosoftNETTestSdkVersion>16.7.0-preview-20200408-06</MicrosoftNETTestSdkVersion>
<MicrosoftDotNetXHarnessTestsRunnersVersion>1.0.0-prerelease.20214.2</MicrosoftDotNetXHarnessTestsRunnersVersion>
<XUnitVersion>2.4.1</XUnitVersion>
<TraceEventVersion>2.0.5</TraceEventVersion>
<NewtonsoftJsonVersion>12.0.3</NewtonsoftJsonVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<DefineConstants>$(DefineConstants);XMLSERIALIZERGENERATORTESTS</DefineConstants>
<TargetFrameworks>$(NetCoreAppCurrent)</TargetFrameworks>
<CoverageSupported>false</CoverageSupported>
<SkipTestsOnPlatform Condition="'$(TargetArchitecture)' == 'arm' or '$(TargetArchitecture)' == 'arm64' or '$(TargetArchitecture)' == 'armel' or '$(TargetArchitecture)' == 'wasm'">true</SkipTestsOnPlatform>
<SkipTestsOnPlatform Condition="'$(TargetOS)' == 'iOS' or '$(TargetOS)' == 'tvOS' or '$(TargetArchitecture)' == 'arm' or '$(TargetArchitecture)' == 'arm64' or '$(TargetArchitecture)' == 'armel' or '$(TargetArchitecture)' == 'wasm'">true</SkipTestsOnPlatform>
</PropertyGroup>
<PropertyGroup>
<!-- Reuse the same runtimeconfig used by MSBuild. -->
Expand Down
2 changes: 2 additions & 0 deletions src/libraries/Native/Unix/System.Native/pal_log.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

PALEXPORT void SystemNative_Log(uint8_t* buffer, int32_t length);

PALEXPORT int32_t SystemNative_InitializeTerminalAndSignalHandling(void);

// Called by pal_signal.cpp to reinitialize the console on SIGCONT/SIGCHLD.
void ReinitializeTerminal(void) {}
void UninitializeTerminal(void) {}
5 changes: 5 additions & 0 deletions src/libraries/Native/Unix/System.Native/pal_log.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,9 @@ void SystemNative_Log (uint8_t* buffer, int32_t length)
NSLog (@"%@", msg);
}
[msg release];
}

int32_t SystemNative_InitializeTerminalAndSignalHandling(void)
{
return 0;
}
60 changes: 49 additions & 11 deletions src/mono/mono.proj
Original file line number Diff line number Diff line change
Expand Up @@ -890,34 +890,72 @@

<Import Project="Directory.Build.targets" />


<Target Name="BuildAppleAppBuilder">
<MSBuild Projects="$(MonoProjectRoot)msbuild\AppleAppBuilder\AppleAppBuilder.csproj"
Properties="Configuration=$(Configuration)"
Targets="Restore;Build" />
<MSBuild Projects="$(MonoProjectRoot)msbuild\AppleTestRunner\AppleTestRunner.csproj"
Properties="Configuration=$(Configuration)"
Targets="Restore;Build" />
</Target>

<UsingTask TaskName="AppleAppBuilderTask"
AssemblyFile="$(ArtifactsObjDir)mono\AppleAppBuilder\$(TargetArchitecture)\$(Configuration)\AppleAppBuilder.dll" />

<Target Name="BuildAppleApp" DependsOnTargets="BuildAppleAppBuilder">
<AppleAppBuilderTask
<Target Name="BuildAppleTestBundle" DependsOnTargets="BuildAppleAppBuilder">
<PropertyGroup>
<TestDir>$(ArtifactsDir)bin\$(TestName)\$(NetCoreAppCurrent)-$(Configuration)</TestDir>
<TestDir Condition="!Exists('$(TestDir)')">$(ArtifactsDir)bin\$(TestName)\$(NetCoreAppCurrent)-Unix-$(Configuration)</TestDir>
<BclDir>$(ArtifactsDir)bin\runtime\$(NetCoreAppCurrent)-$(TargetOS)-$(Configuration)-$(TargetArchitecture)</BclDir>
<BundleDir>$(TestDir)\Bundle</BundleDir>
</PropertyGroup>
<ItemGroup>
<TestBinaries Include="$(TestDir)\*.*"/>
<AppleTestRunnerBinaries Include="msbuild\AppleTestRunner\bin\*.*" />
<BclBinaries Include="$(BclDir)\*.*" Exclude="$(BclDir)\System.Runtime.WindowsRuntime.dll" />
<MonoRuntimeBinaries Include="$(BinDir)\*.*" />
</ItemGroup>

<Error Condition="'$(TestName)' == ''" Text="TestName is not set" />
<Error Condition="!Exists('$(TestDir)')" Text="TestDir=$(TestDir) doesn't exist" />
<Error Condition="!Exists('$(BclDir)')" Text="BclDir=$(BclDir) doesn't exist" />

<RemoveDir Directories="$(BundleDir)" />

<Copy SourceFiles="@(TestBinaries)" DestinationFolder="$(BundleDir)" SkipUnchangedFiles="true"/>
<Copy SourceFiles="@(AppleTestRunnerBinaries)" DestinationFolder="$(BundleDir)\%(RecursiveDir)" SkipUnchangedFiles="true"/>
<Copy SourceFiles="@(BclBinaries)" DestinationFolder="$(BundleDir)\%(RecursiveDir)" SkipUnchangedFiles="true"/>
<Copy SourceFiles="@(MonoRuntimeBinaries)" DestinationFolder="$(BundleDir)\%(RecursiveDir)" SkipUnchangedFiles="true"/>

<AppleAppBuilderTask
Arch="$(TargetArchitecture)"
ProjectName="$(ProjectName)"
Optimized="$(Optimized)"
MonoInclude="$(BinDir)include\mono-2.0"
ProjectName="$(TestName)"
MonoRuntimeHeaders="$(BinDir)include\mono-2.0"
CrossCompiler="$(BinDir)cross\mono-aot-cross"
MainLibraryFileName="$(MainLibraryFileName)"
NativeMainSource="$(NativeMainSource)"
GenerateXcodeProject="$(GenerateXcodeProject)"
BuildAppBundle="$(BuildAppBundle)"
MainLibraryFileName="AppleTestRunner.dll"
UseConsoleUITemplate="True"
GenerateXcodeProject="True"
BuildAppBundle="True"
DevTeamProvisioning="$(DevTeamProvisioning)"
OutputDirectory="$(BinDir)\$(ProjectName)"
AppDir="$(AppDir)">
OutputDirectory="$(BundleDir)"
AppDir="$(BundleDir)">
<Output TaskParameter="AppBundlePath" PropertyName="AppBundlePath" />
<Output TaskParameter="XcodeProjectPath" PropertyName="XcodeProjectPath" />
</AppleAppBuilderTask>
<Message Importance="High" Text="Xcode: $(XcodeProjectPath)"/>
<Message Importance="High" Text="App: $(AppBundlePath)"/>

<!-- Demo: use xcrun to deploy & launch on a simulator
to be replaced with xharness

For quite mode: %dashdash%auto-exit before "testlib:" and 'open -a Simulator' can be removed
-->
<Exec Condition="'$(TargetArchitecture)' == 'x64'" Command="xcrun simctl shutdown &quot;iPhone 11&quot;" ContinueOnError="WarnAndContinue" />
<Exec Condition="'$(TargetArchitecture)' == 'x64'" Command="xcrun simctl boot &quot;iPhone 11&quot;" />
<Exec Condition="'$(TargetArchitecture)' == 'x64' and '$(ShowIosSimulator)' != 'false'" Command="open -a Simulator" />
<Exec Condition="'$(TargetArchitecture)' == 'x64'" Command="xcrun simctl install &quot;iPhone 11&quot; $(AppBundlePath)" />
<Exec Condition="'$(TargetArchitecture)' == 'x64'" Command="xcrun simctl launch --console booted net.dot.$(TestName) testlib:$(TestName).dll" />
</Target>

<!-- Ordering matters! Overwriting the Build target. -->
Expand Down
5 changes: 3 additions & 2 deletions src/mono/msbuild/AppleAppBuilder/AotCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,11 @@ private static void PrecompileLibrary(
.Append("static,")
.Append("asmonly,")
.Append("direct-icalls,")
.Append("no-direct-calls,")
.Append("nodebug,")
.Append("dwarfdebug,")
.Append("outfile=").Append(Path.Combine(binDir, libName + ".dll.s,"))
// TODO: enable aotdata
.Append("msym-dir=").Append(Path.Combine(binDir, "Msym,"))
// TODO: enable aotdata
//.Append("data-outfile=").Append(Path.Combine(binDir, libName + ".aotdata,"))
// TODO: enable direct-pinvokes (to get rid of -force_loads)
//.Append("direct-pinvoke,")
Expand Down
11 changes: 6 additions & 5 deletions src/mono/msbuild/AppleAppBuilder/AppleAppBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class AppleAppBuilderTask : Task
/// Path to Mono public headers (*.h)
/// </summary>
[Required]
public string MonoInclude { get; set; } = ""!;
public string MonoRuntimeHeaders { get; set; } = ""!;
Copy link
Member

Choose a reason for hiding this comment

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

What does ""! achieve here? Is this the "null-forgiving" operator?

Copy link
Member Author

Choose a reason for hiding this comment

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

These properties are guaranteed to be non-null always (due to [Required] attribute) the compiler forces me to do inline init to leave them non-nullable. I wonder how @stephentoub solves such cases.


/// <summary>
/// This library will be used as an entry-point (e.g. TestRunner.dll)
Expand Down Expand Up @@ -122,8 +122,10 @@ public override bool Execute()
throw new ArgumentException($"MainLibraryFileName='{MainLibraryFileName}' was not found in AppDir='{AppDir}'");
}

// escape spaces
ProjectName = ProjectName.Replace(" ", "-");
if (ProjectName.Contains(" "))
{
throw new ArgumentException($"ProjectName='{ProjectName}' should not contain spaces");
}

string[] excludes = new string[0];
if (ExcludeFromAppDir != null)
Expand Down Expand Up @@ -163,7 +165,7 @@ public override bool Execute()
if (GenerateXcodeProject)
{
XcodeProjectPath = Xcode.GenerateXCode(ProjectName, MainLibraryFileName,
AppDir, binDir, MonoInclude, UseConsoleUITemplate, NativeMainSource);
AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, NativeMainSource);

if (BuildAppBundle)
{
Expand All @@ -179,7 +181,6 @@ public override bool Execute()
Arch, Optimized, DevTeamProvisioning);
}
}
Utils.LogInfo($"Xcode: {XcodeProjectPath}\n App: {AppBundlePath}");
}

return true;
Expand Down
11 changes: 6 additions & 5 deletions src/mono/msbuild/AppleAppBuilder/Templates/main-console.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ - (void)viewDidLoad {

CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame];
logLabel = [[UITextView alloc] initWithFrame:
CGRectMake(2.0, 50.0, applicationFrame.size.width, applicationFrame.size.height)];
CGRectMake(2.0, 50.0, applicationFrame.size.width - 2.0, applicationFrame.size.height - 50.0)];
logLabel.font = [UIFont systemFontOfSize:9.0];
logLabel.backgroundColor = [UIColor blackColor];
logLabel.textColor = [UIColor greenColor];
Expand All @@ -43,7 +43,7 @@ - (void)viewDidLoad {
logLabel.editable = NO;
logLabel.clipsToBounds = YES;

summaryLabel = [[UILabel alloc] initWithFrame: CGRectMake(10.0, 0.0, applicationFrame.size.width, 50)];
summaryLabel = [[UILabel alloc] initWithFrame: CGRectMake(10.0, 0.0, applicationFrame.size.width - 10.0, 50)];
summaryLabel.textColor = [UIColor whiteColor];
summaryLabel.font = [UIFont boldSystemFontOfSize: 14];
summaryLabel.numberOfLines = 2;
Expand Down Expand Up @@ -80,9 +80,10 @@ - (void)viewDidLoad {
NSString* nsstr = [NSString stringWithUTF8String:strdup(value)];
dispatch_async(dispatch_get_main_queue(), ^{
logLabel.text = [logLabel.text stringByAppendingString:nsstr];
dispatch_async(dispatch_get_main_queue(), ^{
[logLabel scrollRangeToVisible: NSMakeRange(logLabel.text.length -1, 1)];
});
CGRect caretRect = [logLabel caretRectForPosition:logLabel.endOfDocument];
[logLabel scrollRectToVisible:caretRect animated:NO];
[logLabel setScrollEnabled:NO];
[logLabel setScrollEnabled:YES];
});
Copy link
Member Author

Choose a reason for hiding this comment

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

Some hack to automatically scroll to the bottom in UITextView

Copy link
Member

Choose a reason for hiding this comment

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

why do you need to toggle setScrollEnabled? is the scrollRectToVisible not enough?

Copy link
Member Author

Choose a reason for hiding this comment

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

@akoeplinger I don't know but without it doesn't work properly, I tried different hacks from SO this one works as expected (https://stackoverflow.com/questions/19124037/scroll-to-bottom-of-uitextview-erratic-in-ios-7/20989956#20989956)

}

Expand Down
4 changes: 3 additions & 1 deletion src/mono/msbuild/AppleAppBuilder/Templates/runtime.m
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,11 @@
const char* bundle = get_bundle_path ();
chdir (bundle);

register_dllmap ();
// TODO: set TRUSTED_PLATFORM_ASSEMBLIES, APP_PATHS and NATIVE_DLL_SEARCH_DIRECTORIES
monovm_initialize(0, NULL, NULL);

#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
register_dllmap ();
// register modules
mono_ios_register_modules ();
mono_jit_set_aot_mode (MONO_AOT_MODE_FULL);
Expand Down
34 changes: 26 additions & 8 deletions src/mono/msbuild/AppleAppBuilder/Xcode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ public static string GenerateXCode(
string workspace,
string binDir,
string monoInclude,
bool useConsoleUiTemplate = false,
bool preferDylibs,
bool useConsoleUiTemplate,
string? nativeMainSource = null)
{
// bundle everything as resources excluding native files
string[] excludes = {".dylib", ".dll.o", ".dll.s", ".dwarf", ".m", ".h", ".a"};
string[] excludes = {".dll.o", ".dll.s", ".dwarf", ".m", ".h", ".a"};

string[] resources = Directory.GetFiles(workspace)
.Where(f => !excludes.Any(e => f.EndsWith(e, StringComparison.InvariantCultureIgnoreCase)))
.Concat(Directory.GetFiles(binDir, "*.aotdata"))
Expand Down Expand Up @@ -49,12 +51,20 @@ public static string GenerateXCode(
.Replace("%MainSource%", nativeMainSource)
.Replace("%MonoInclude%", monoInclude);

string[] dylibs = Directory.GetFiles(workspace, "*.dylib");
string toLink = "";
foreach (string lib in Directory.GetFiles(workspace, "*.a"))
{
// these libraries are pinvoked
// -force_load will be removed once we enable direct-pinvokes for AOT
toLink += $" \"-force_load {lib}\"{Environment.NewLine}";
string libName = Path.GetFileNameWithoutExtension(lib);
// libmono must always be statically linked, for other librarires we can use dylibs
bool dylibExists = libName != "libmono" && dylibs.Any(dylib => Path.GetFileName(dylib) == libName + ".dylib");

if (!preferDylibs || !dylibExists)
{
// these libraries are pinvoked
// -force_load will be removed once we enable direct-pinvokes for AOT
toLink += $" \"-force_load {lib}\"{Environment.NewLine}";
}
}
foreach (string lib in Directory.GetFiles(binDir, "*.dll.o"))
{
Expand Down Expand Up @@ -83,12 +93,20 @@ public static string GenerateXCode(
Utils.GetEmbeddedResource("runtime.h"));

// forward pinvokes to "__Internal"
string dllMap = string.Join(Environment.NewLine, Directory.GetFiles(workspace, "*.a")
.Select(f => $" mono_dllmap_insert (NULL, \"{Path.GetFileNameWithoutExtension(f)}\", NULL, \"__Internal\", NULL);"));
var dllMap = new StringBuilder();
foreach (string aFile in Directory.GetFiles(workspace, "*.a"))
{
string aFileName = Path.GetFileNameWithoutExtension(aFile);
dllMap.AppendLine($" mono_dllmap_insert (NULL, \"{aFileName}\", NULL, \"__Internal\", NULL);");

// also register with or without "lib" prefix
EgorBo marked this conversation as resolved.
Show resolved Hide resolved
aFileName = aFileName.StartsWith("lib") ? aFileName.Remove(0, 3) : "lib" + aFileName;
dllMap.AppendLine($" mono_dllmap_insert (NULL, \"{aFileName}\", NULL, \"__Internal\", NULL);");
}

File.WriteAllText(Path.Combine(binDir, "runtime.m"),
Utils.GetEmbeddedResource("runtime.m")
.Replace("//%DllMap%", dllMap)
.Replace("//%DllMap%", dllMap.ToString())
.Replace("%EntryPointLibName%", Path.GetFileName(entryPointLib)));

Utils.RunProcess("cmake", cmakeArgs.ToString(), workingDir: binDir);
Expand Down
Loading