[xharness] Major rewrite (add server mode, add device support, add today extension support).
* Add a server mode, which launches a web server (and a web page) that can be used to interactively run tests and view their results. * Add support for running test assemblies in a today extension (generating a new set of projects, similar to how we generate tvOS/watchOS projects based on the iOS project, we now generate a today extension project in addition to the tvOS and watchOS projects). * Load all the different tests (and show them in the html report, although they show up as 'ignored'), even for disabled/ignored tests. This makes disabled/ignored tests more visible, and also makes it possible to actually run them using the embedded web server. * Add support for running tests on device. Tests will be executed on multiple devices simulatenously (any connected devices will be used).
This commit is contained in:
Родитель
39cb42961d
Коммит
8391a3ca39
|
@ -18,6 +18,9 @@ build
|
|||
*-unifiedXM45.sln
|
||||
*-unified-32.sln
|
||||
*-unifiedXM45-32.sln
|
||||
*-today.?sproj
|
||||
*-today-extension.?sproj
|
||||
*-today.sln
|
||||
Makefile-mac.inc
|
||||
.stamp*
|
||||
Info-*.plist
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)-unified</IntermediateOutputPath>
|
||||
<DefineConstants>XAMCORE_2_0</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' Or '$(Configuration)' == 'Debug32' Or '$(Configuration)' == 'Debug64' ">
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>False</Optimize>
|
||||
|
@ -27,7 +27,7 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' Or '$(Configuration)' == 'Release32' Or '$(Configuration)' == 'Release64' Or '$(Configuration)' == 'Release-bitcode' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>True</Optimize>
|
||||
<OutputPath>bin\Any CPU\$(Configuration)-unified</OutputPath>
|
||||
|
@ -36,17 +36,6 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release-bitcode' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>True</Optimize>
|
||||
<OutputPath>bin\Any CPU\$(Configuration)-bitcode-unified</OutputPath>
|
||||
<DefineConstants>DO_NOT_REMOVE;FRAMEWORK_TEST;$(DefineConstants)</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
<MtouchExtraArgs>--bitcode:full</MtouchExtraArgs>
|
||||
<MtouchUseLlvm>true</MtouchUseLlvm>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="Xamarin.iOS" />
|
||||
|
@ -85,7 +74,16 @@
|
|||
<Link>libframework.h</Link>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<Target Name="BeforeBuild" Inputs="..\..\tests\test-libraries\libframework.m" Outputs="..\..\tests\test-libraries\.libs\ios\XTest.framework ..\..\tests\test-libraries\.libs\ios\XSharedObjectTest.framework ..\..\tests\test-libraries\.libs\ios\XSharedARTest.framework">
|
||||
<Exec Command="make -j8 -C ..\..\tests\test-libraries" />
|
||||
<ItemGroup>
|
||||
<TestLibrariesInput Include="..\..\tests\test-libraries\libframework.m" />
|
||||
<TestLibrariesOutput Include="..\..\tests\test-libraries\.libs\ios\XTest.framework" />
|
||||
<TestLibrariesOutput Include="..\..\tests\test-libraries\.libs\ios\XSharedObjectTest.framework" />
|
||||
<TestLibrariesOutput Include="..\..\tests\test-libraries\.libs\ios\XSharedARTest.framework" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<TestLibrariesDirectory>..\..\tests\test-libraries</TestLibrariesDirectory>
|
||||
</PropertyGroup>
|
||||
<Target Name="BeforeBuild" Inputs="@(TestLibrariesInput)" Outputs="@(TestLibrariesOutput)">
|
||||
<Exec Command="make -j8 -C $(TestLibrariesDirectory)" />
|
||||
</Target>
|
||||
</Project>
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>TestApp</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>%CFBUNDLEIDENTIFIER%</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>TestApp</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>%MINOSVERSION%</string>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
|
||||
using Foundation;
|
||||
using UIKit;
|
||||
|
||||
using MonoTouch.NUnit.UI;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Internal;
|
||||
|
||||
[Register ("AppDelegate")]
|
||||
public partial class AppDelegate : UIApplicationDelegate
|
||||
{
|
||||
UIWindow window;
|
||||
TouchRunner runner;
|
||||
|
||||
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
|
||||
{
|
||||
window = new UIWindow (UIScreen.MainScreen.Bounds);
|
||||
|
||||
runner = new TouchRunner (window);
|
||||
runner.Add (System.Reflection.Assembly.GetExecutingAssembly ());
|
||||
|
||||
window.RootViewController = new UINavigationController (runner.GetViewController ());
|
||||
window.MakeKeyAndVisible ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Main (string[] args)
|
||||
{
|
||||
UIApplication.Main (args, null, typeof (AppDelegate));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[TestFixture]
|
||||
class Dummy
|
||||
{
|
||||
[Test]
|
||||
public void Test ()
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{0cefdfbf-2581-4d8a-af34-a505ef2f3014}</ProjectGuid>
|
||||
<ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>TodayContainer</RootNamespace>
|
||||
<TargetFrameworkIdentifier>Xamarin.iOS</TargetFrameworkIdentifier>
|
||||
<AssemblyName>TodayContainer</AssemblyName>
|
||||
<OutputPath>bin\$(Platform)\$(Configuration)-today</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Platform)' == 'iPhoneSimulator' ">
|
||||
<MtouchArch>x86_64</MtouchArch>
|
||||
<MtouchLink>None</MtouchLink>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Platform)' == 'iPhone' ">
|
||||
<MtouchArch>ARM64</MtouchArch>
|
||||
<MtouchLink>Full</MtouchLink>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' Or '$(Configuration)' == 'Debug32' Or '$(Configuration)' == 'Debug64' ">
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>False</Optimize>
|
||||
<MtouchDebug>True</MtouchDebug>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' Or '$(Configuration)' == 'Release32' Or '$(Configuration)' == 'Release64' ">
|
||||
<DebugSymbols>False</DebugSymbols>
|
||||
<Optimize>True</Optimize>
|
||||
<MtouchDebug>False</MtouchDebug>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Xamarin.iOS" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="MonoTouch.NUnitLite" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Info.plist">
|
||||
<LogicalName>Info.plist</LogicalName>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Main.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="TodayExtension.csproj">
|
||||
<IsAppExtension>true</IsAppExtension>
|
||||
<Project>{FBF6DD7B-A275-4161-B75F-5E24D303D826}</Project>
|
||||
<Name>TodayExtension</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
|
||||
</Project>
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>TodayExtension</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>%CFBUNDLEIDENTIFIER%</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>TodayExtension</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>8.0</string>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionMainStoryboard</key>
|
||||
<string>TodayView</string>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.widget-extension</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
|
||||
using NotificationCenter;
|
||||
using Foundation;
|
||||
using UIKit;
|
||||
|
||||
using MonoTouch.NUnit.UI;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Internal;
|
||||
|
||||
[Register ("TodayViewController")]
|
||||
public partial class TodayViewController : UIViewController, INCWidgetProviding
|
||||
{
|
||||
ConsoleRunner runner;
|
||||
|
||||
protected TodayViewController (IntPtr handle) : base (handle) {}
|
||||
|
||||
[Export ("widgetPerformUpdateWithCompletionHandler:")]
|
||||
public void WidgetPerformUpdate (Action<NCUpdateResult> completionHandler)
|
||||
{
|
||||
runner = new ConsoleRunner ();
|
||||
runner.Add (System.Reflection.Assembly.GetExecutingAssembly ());
|
||||
System.Threading.ThreadPool.QueueUserWorkItem ((v) =>
|
||||
{
|
||||
runner.LoadSync ();
|
||||
BeginInvokeOnMainThread (() =>
|
||||
{
|
||||
runner.AutoRun ();
|
||||
});
|
||||
});
|
||||
|
||||
completionHandler (NCUpdateResult.NewData);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{bcdac24e-67a7-427b-bcab-d9a080bdd71b}</ProjectGuid>
|
||||
<ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<TargetFrameworkIdentifier>Xamarin.iOS</TargetFrameworkIdentifier>
|
||||
<OutputType>Library</OutputType>
|
||||
<AssemblyName>TodayExtension</AssemblyName>
|
||||
<IntermediateOutputPath>obj\$(Platform)\ios</IntermediateOutputPath>
|
||||
<OutputPath>bin\$(Platform)\ios</OutputPath>
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>False</Optimize>
|
||||
<MtouchLink>%MTOUCH_LINK%</MtouchLink>
|
||||
<MtouchExtraArgs>%MTOUCH_EXTRAARGS%</MtouchExtraArgs>
|
||||
<MtouchDebug>%MTOUCH_DEBUG%</MtouchDebug>
|
||||
<MtouchProfiling>%MTOUCH_PROFILING%</MtouchProfiling>
|
||||
<MtouchUseLlvm>%MTOUCH_USELLVM%</MtouchUseLlvm>
|
||||
<MtouchEnableBitcode>%MTOUCH_ENABLEBITCODE%</MtouchEnableBitcode>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Platform)' == 'iPhoneSimulator' ">
|
||||
<MtouchArch>i386, x86_64</MtouchArch>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Platform)' == 'iPhone' ">
|
||||
<MtouchArch>ARMv7, ARM64</MtouchArch>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Xamarin.iOS" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="MonoTouch.NUnitLite" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Info.plist">
|
||||
<LogicalName>Info.plist</LogicalName>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<InterfaceDefinition Include="TodayView.storyboard" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Main.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.AppExtension.CSharp.targets" />
|
||||
</Project>
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6095.1" systemVersion="13D37" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="M4Y-Lb-cyx">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6100" />
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--My Widget View Controller-->
|
||||
<scene sceneID="cwh-vc-ff4">
|
||||
<objects>
|
||||
<viewController id="M4Y-Lb-cyx" customClass="TodayViewController" customModuleProvider="" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="Ft6-oW-KC0" />
|
||||
<viewControllerLayoutGuide type="bottom" id="FKl-LY-JtV" />
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" simulatedAppContext="notificationCenter" id="S3S-Oj-5AN">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="37" />
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" />
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="top" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Hello World" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0"
|
||||
baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" preferredMaxLayoutWidth="280" translatesAutoresizingMaskIntoConstraints="NO" id="GcN-lo-r42">
|
||||
<rect key="frame" x="20" y="8" width="280" height="21" />
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES" />
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17" />
|
||||
<color key="textColor" cocoaTouchSystemColor="lightTextColor" />
|
||||
<nil key="highlightedColor" />
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="FKl-LY-JtV" firstAttribute="top" secondItem="GcN-lo-r42" secondAttribute="bottom" constant="20" symbolic="YES" id="0Q0-KW-PJ6" />
|
||||
<constraint firstItem="GcN-lo-r42" firstAttribute="leading" secondItem="S3S-Oj-5AN" secondAttribute="leading" constant="20" symbolic="YES" id="6Vq-gs-PHe" />
|
||||
<constraint firstAttribute="trailing" secondItem="GcN-lo-r42" secondAttribute="trailing" constant="20" symbolic="YES" id="L8K-9R-egU" />
|
||||
<constraint firstItem="GcN-lo-r42" firstAttribute="top" secondItem="Ft6-oW-KC0" secondAttribute="bottom" constant="20" symbolic="YES" id="mYS-Cv-VNx" />
|
||||
</constraints>
|
||||
</view>
|
||||
<extendedEdge key="edgesForExtendedLayout" />
|
||||
<nil key="simulatedStatusBarMetrics" />
|
||||
<nil key="simulatedTopBarMetrics" />
|
||||
<nil key="simulatedBottomBarMetrics" />
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics" />
|
||||
<size key="freeformSize" width="320" height="37" />
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="vXp-U4-Rya" userLabel="First Responder" sceneMemberID="firstResponder" />
|
||||
</objects>
|
||||
<point key="canvasLocation" x="516" y="285" />
|
||||
</scene>
|
||||
</scenes>
|
||||
<simulatedMetricsContainer key="defaultSimulatedMetrics">
|
||||
<simulatedStatusBarMetrics key="statusBar" />
|
||||
<simulatedOrientationMetrics key="orientation" />
|
||||
<simulatedScreenMetrics key="destination" type="retina4" />
|
||||
</simulatedMetricsContainer>
|
||||
</document>
|
|
@ -76,7 +76,7 @@
|
|||
<ImageAsset Include="%WATCHAPP_PATH%Resources\Images.xcassets\AppIcons.appiconset\Contents.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Info-watchos-app.plist">
|
||||
<None Include="Info.plist">
|
||||
<LogicalName>Info.plist</LogicalName>
|
||||
</None>
|
||||
<None Include="%WATCHAPP_PATH%Entitlements.plist" />
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleName</key>
|
||||
<string>Don't Link</string>
|
||||
<string>TestApp</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>%APP_CFBUNDLEIDENTIFER%</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
|
@ -20,7 +20,7 @@
|
|||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
</array>
|
||||
<key>WKCompanionAppBundleIdentifier</key>
|
||||
<string>com.xamarin.dontlink</string>
|
||||
<string>%CONTAINER_CFBUNDLEIDENTIFIER%</string>
|
||||
<key>WKWatchKitApp</key>
|
||||
<true/>
|
||||
<key>XSAppIconAssets</key>
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
<MtouchArch>i386</MtouchArch>
|
||||
<MtouchLink>None</MtouchLink>
|
||||
<MtouchFastDev>true</MtouchFastDev>
|
||||
<MtouchDebug>true</MtouchDebug>
|
||||
<CodesignKey>iPhone Developer</CodesignKey>
|
||||
<MtouchProfiling>true</MtouchProfiling>
|
||||
|
@ -64,7 +63,6 @@
|
|||
<CodesignKey>iPhone Developer</CodesignKey>
|
||||
<DeviceSpecificBuild>true</DeviceSpecificBuild>
|
||||
<MtouchDebug>true</MtouchDebug>
|
||||
<MtouchFastDev>true</MtouchFastDev>
|
||||
<MtouchProfiling>true</MtouchProfiling>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>TestApp</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>%CFBUNDLEIDENTIFIER%</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>TestApp</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>%MINOSVERSION%</string>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
|
||||
using Foundation;
|
||||
using UIKit;
|
||||
|
||||
using MonoTouch.NUnit.UI;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Internal;
|
||||
|
||||
[Register ("AppDelegate")]
|
||||
public partial class AppDelegate : UIApplicationDelegate
|
||||
{
|
||||
UIWindow window;
|
||||
TouchRunner runner;
|
||||
|
||||
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
|
||||
{
|
||||
window = new UIWindow (UIScreen.MainScreen.Bounds);
|
||||
|
||||
runner = new TouchRunner (window);
|
||||
runner.Add (System.Reflection.Assembly.GetExecutingAssembly ());
|
||||
|
||||
window.RootViewController = new UINavigationController (runner.GetViewController ());
|
||||
window.MakeKeyAndVisible ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Main (string[] args)
|
||||
{
|
||||
UIApplication.Main (args, null, typeof (AppDelegate));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{0cefdfbf-2581-4d8a-af34-a505ef2f3014}</ProjectGuid>
|
||||
<ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<TargetFrameworkIdentifier>Xamarin.iOS</TargetFrameworkIdentifier>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AssemblyName>iOSApp</AssemblyName>
|
||||
<IntermediateOutputPath>obj\$(Platform)\ios</IntermediateOutputPath>
|
||||
<OutputPath>bin\$(Platform)\ios</OutputPath>
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>False</Optimize>
|
||||
<MtouchLink>%MTOUCH_LINK%</MtouchLink>
|
||||
<MtouchExtraArgs>%MTOUCH_EXTRAARGS%</MtouchExtraArgs>
|
||||
<MtouchDebug>%MTOUCH_DEBUG%</MtouchDebug>
|
||||
<MtouchProfiling>%MTOUCH_PROFILING%</MtouchProfiling>
|
||||
<MtouchUseLlvm>%MTOUCH_USELLVM%</MtouchUseLlvm>
|
||||
<MtouchEnableBitcode>%MTOUCH_ENABLEBITCODE%</MtouchEnableBitcode>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Platform)' == 'iPhoneSimulator' ">
|
||||
<MtouchArch>%SIMULATOR_ARCH%</MtouchArch>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Platform)' == 'iPhone' ">
|
||||
<MtouchArch>%DEVICE_ARCH%</MtouchArch>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Xamarin.iOS" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="MonoTouch.NUnitLite" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Info.plist">
|
||||
<LogicalName>Info.plist</LogicalName>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Main.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
%PROJECT_REFERENCES%
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>TestApp</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>%CFBUNDLEIDENTIFIER%</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>TestApp</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>9.0</string>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>4</integer>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
|
||||
using Foundation;
|
||||
using UIKit;
|
||||
|
||||
using MonoTouch.NUnit.UI;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Internal;
|
||||
|
||||
[Register ("AppDelegate")]
|
||||
public partial class AppDelegate : UIApplicationDelegate
|
||||
{
|
||||
UIWindow window;
|
||||
TouchRunner runner;
|
||||
|
||||
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
|
||||
{
|
||||
window = new UIWindow (UIScreen.MainScreen.Bounds);
|
||||
|
||||
runner = new TouchRunner (window);
|
||||
runner.Add (System.Reflection.Assembly.GetExecutingAssembly ());
|
||||
|
||||
window.RootViewController = new UINavigationController (runner.GetViewController ());
|
||||
window.MakeKeyAndVisible ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Main (string[] args)
|
||||
{
|
||||
UIApplication.Main (args, null, typeof (AppDelegate));
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class SimpleTest
|
||||
{
|
||||
[Test]
|
||||
public void Success ()
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{0cefdfbf-2581-4d8a-af34-a505ef2f3014}</ProjectGuid>
|
||||
<ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<TargetFrameworkIdentifier>Xamarin.TVOS</TargetFrameworkIdentifier>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AssemblyName>tvOSApp</AssemblyName>
|
||||
<IntermediateOutputPath>obj\$(Platform)\tvos</IntermediateOutputPath>
|
||||
<OutputPath>bin\$(Platform)\tvos</OutputPath>
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>False</Optimize>
|
||||
<MtouchLink>%MTOUCH_LINK%</MtouchLink>
|
||||
<MtouchExtraArgs>%MTOUCH_EXTRAARGS%</MtouchExtraArgs>
|
||||
<MtouchDebug>%MTOUCH_DEBUG%</MtouchDebug>
|
||||
<MtouchProfiling>%MTOUCH_PROFILING%</MtouchProfiling>
|
||||
<MtouchUseLlvm>%MTOUCH_USELLVM%</MtouchUseLlvm>
|
||||
<MtouchEnableBitcode>%MTOUCH_ENABLEBITCODE%</MtouchEnableBitcode>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Platform)' == 'iPhoneSimulator' ">
|
||||
<MtouchArch>%SIMULATOR_ARCH%</MtouchArch>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Platform)' == 'iPhone' ">
|
||||
<MtouchArch>%DEVICE_ARCH%</MtouchArch>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Xamarin.TVOS" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="MonoTouch.NUnitLite" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Info.plist">
|
||||
<LogicalName>Info.plist</LogicalName>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Main.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\TVOS\Xamarin.TVOS.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
%PROJECT_REFERENCES%
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,2 @@
|
|||
tmp-test-dir
|
||||
|
|
@ -26,10 +26,17 @@ namespace xharness
|
|||
Device_watchOS,
|
||||
}
|
||||
|
||||
public enum Extension
|
||||
{
|
||||
WatchKit2,
|
||||
TodayExtension,
|
||||
}
|
||||
|
||||
public class AppRunner
|
||||
{
|
||||
public Harness Harness;
|
||||
public string ProjectFile;
|
||||
public string AppPath;
|
||||
|
||||
public TestExecutingResult Result { get; private set; }
|
||||
|
||||
|
@ -38,11 +45,34 @@ namespace xharness
|
|||
string launchAppPath;
|
||||
string bundle_identifier;
|
||||
string platform;
|
||||
Extension? extension;
|
||||
bool isSimulator;
|
||||
|
||||
string device_name;
|
||||
string companion_device_name;
|
||||
|
||||
string configuration;
|
||||
public string Configuration {
|
||||
get { return configuration ?? Harness.Configuration; }
|
||||
set { configuration = value; }
|
||||
}
|
||||
|
||||
public string DeviceName {
|
||||
get { return device_name; }
|
||||
set { device_name = value; }
|
||||
}
|
||||
|
||||
public string CompanionDeviceName {
|
||||
get { return companion_device_name; }
|
||||
set { companion_device_name = value; }
|
||||
}
|
||||
|
||||
public bool isExtension {
|
||||
get {
|
||||
return extension.HasValue;
|
||||
}
|
||||
}
|
||||
|
||||
// For watch apps we end up with 2 simulators, the watch simulator (the main one), and the iphone simulator (the companion one).
|
||||
SimDevice[] simulators;
|
||||
SimDevice simulator { get { return simulators [0]; } }
|
||||
|
@ -147,14 +177,8 @@ namespace xharness
|
|||
}
|
||||
device_name = selected_data.Name;
|
||||
|
||||
if (mode == "watchos") {
|
||||
var companion = devs.ConnectedDevices.Where ((v) => v.DeviceIdentifier == selected_data.CompanionIdentifier);
|
||||
if (companion.Count () == 0)
|
||||
throw new Exception ($"Could not find the companion device for '{selected_data.Name}'");
|
||||
else if (companion.Count () > 1)
|
||||
main_log.WriteLine ("Found {0} companion devices for {1}?!?", companion.Count (), selected_data.Name);
|
||||
companion_device_name = companion.First ().Name;
|
||||
}
|
||||
if (mode == "watchos")
|
||||
companion_device_name = devs.FindCompanionDevice (main_log, selected_data).Name;
|
||||
}
|
||||
|
||||
bool initialized;
|
||||
|
@ -169,9 +193,13 @@ namespace xharness
|
|||
appName = csproj.GetAssemblyName ();
|
||||
var info_plist_path = csproj.GetInfoPListInclude ();
|
||||
var info_plist = new XmlDocument ();
|
||||
info_plist.LoadWithoutNetworkAccess (Path.Combine (Path.GetDirectoryName (ProjectFile), info_plist_path));
|
||||
info_plist.LoadWithoutNetworkAccess (Path.Combine (Path.GetDirectoryName (ProjectFile), info_plist_path.Replace ('\\', '/')));
|
||||
bundle_identifier = info_plist.GetCFBundleIdentifier ();
|
||||
|
||||
var extensionPointIdentifier = info_plist.GetNSExtensionPointIdentifier ();
|
||||
if (!string.IsNullOrEmpty (extensionPointIdentifier))
|
||||
extension = extensionPointIdentifier.ParseFromNSExtensionPointIdentifier ();
|
||||
|
||||
switch (Target) {
|
||||
case AppRunnerTarget.Simulator_iOS32:
|
||||
mode = "sim32";
|
||||
|
@ -217,7 +245,7 @@ namespace xharness
|
|||
throw new Exception (string.Format ("Unknown target: {0}", Harness.Target));
|
||||
}
|
||||
|
||||
appPath = Path.Combine (Path.GetDirectoryName (ProjectFile), csproj.GetOutputPath (platform, Harness.Configuration).Replace ('\\', '/'), appName + ".app");
|
||||
appPath = Path.Combine (Path.GetDirectoryName (ProjectFile), csproj.GetOutputPath (platform, Configuration).Replace ('\\', '/'), appName + (isExtension ? ".appex" : ".app"));
|
||||
if (!Directory.Exists (appPath))
|
||||
throw new Exception (string.Format ("The app directory {0} does not exist. This is probably a bug in the test harness.", appPath));
|
||||
|
||||
|
@ -228,7 +256,7 @@ namespace xharness
|
|||
}
|
||||
}
|
||||
|
||||
public int Install (Log log)
|
||||
public async Task<ProcessExecutionResult> InstallAsync ()
|
||||
{
|
||||
Initialize ();
|
||||
|
||||
|
@ -252,11 +280,10 @@ namespace xharness
|
|||
if (mode == "watchos")
|
||||
args.Append (" --device ios,watchos");
|
||||
|
||||
var rv = ProcessHelper.ExecuteCommandAsync (Harness.MlaunchPath, args.ToString (), log, TimeSpan.FromHours (1)).Result;
|
||||
return rv.Succeeded ? 0 : 1;
|
||||
return await ProcessHelper.ExecuteCommandAsync (Harness.MlaunchPath, args.ToString (), main_log, TimeSpan.FromMinutes (mode == "watchos" ? 15 : 3));
|
||||
}
|
||||
|
||||
public int Uninstall (Log log)
|
||||
public async Task<ProcessExecutionResult> UninstallAsync ()
|
||||
{
|
||||
Initialize ();
|
||||
|
||||
|
@ -275,8 +302,7 @@ namespace xharness
|
|||
args.AppendFormat (" \"{0}\" ", bundle_identifier);
|
||||
AddDeviceName (args, companion_device_name ?? device_name);
|
||||
|
||||
var rv = ProcessHelper.ExecuteCommandAsync (Harness.MlaunchPath, args.ToString (), log, TimeSpan.FromMinutes (1)).Result;
|
||||
return rv.Succeeded ? 0 : 1;
|
||||
return await ProcessHelper.ExecuteCommandAsync (Harness.MlaunchPath, args.ToString (), main_log, TimeSpan.FromMinutes (1));
|
||||
}
|
||||
|
||||
bool ensure_clean_simulator_state = true;
|
||||
|
@ -489,13 +515,46 @@ namespace xharness
|
|||
args.AppendFormat (" -argument=-app-arg:-hostport:{0}", listener.Port);
|
||||
args.AppendFormat (" -setenv=NUNIT_HOSTPORT={0}", listener.Port);
|
||||
|
||||
listener.StartAsync ();
|
||||
|
||||
var cancellation_source = new CancellationTokenSource ();
|
||||
var timed_out = false;
|
||||
|
||||
ThreadPool.QueueUserWorkItem ((v) =>
|
||||
{
|
||||
if (!listener.WaitForConnection (TimeSpan.FromMinutes (Harness.LaunchTimeout))) {
|
||||
cancellation_source.Cancel ();
|
||||
main_log.WriteLine ("Test launch timed out after {0} minute(s).", Harness.LaunchTimeout);
|
||||
timed_out = true;
|
||||
} else {
|
||||
main_log.WriteLine ("Test run started");
|
||||
}
|
||||
});
|
||||
|
||||
foreach (var kvp in Harness.EnvironmentVariables)
|
||||
args.AppendFormat (" -setenv={0}={1}", kvp.Key, kvp.Value);
|
||||
|
||||
bool? success = null;
|
||||
bool timed_out = false;
|
||||
bool launch_failure = false;
|
||||
|
||||
if (isExtension) {
|
||||
switch (extension) {
|
||||
case Extension.TodayExtension:
|
||||
args.Append (isSimulator ? " --launchsimbundleid" : " --launchdevbundleid");
|
||||
args.Append (" todayviewforextensions:");
|
||||
args.Append (BundleIdentifier);
|
||||
args.Append (" --observe-extension ");
|
||||
args.Append (Harness.Quote (launchAppPath));
|
||||
break;
|
||||
case Extension.WatchKit2:
|
||||
default:
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
} else {
|
||||
args.Append (isSimulator ? " --launchsim " : " --launchdev ");
|
||||
args.Append (Harness.Quote (launchAppPath));
|
||||
}
|
||||
|
||||
if (isSimulator) {
|
||||
if (!await FindSimulatorAsync ())
|
||||
return 1;
|
||||
|
@ -537,25 +596,12 @@ namespace xharness
|
|||
await sim.PrepareSimulatorAsync (main_log, bundle_identifier);
|
||||
}
|
||||
|
||||
args.Append (" --launchsim");
|
||||
args.AppendFormat (" \"{0}\" ", launchAppPath);
|
||||
args.Append (" --device=:v2:udid=").Append (simulator.UDID).Append (" ");
|
||||
|
||||
await crash_reports.StartCaptureAsync ();
|
||||
|
||||
listener.StartAsync ();
|
||||
main_log.WriteLine ("Starting test run");
|
||||
|
||||
var cancellation_source = new CancellationTokenSource ();
|
||||
ThreadPool.QueueUserWorkItem ((v) => {
|
||||
if (!listener.WaitForConnection (TimeSpan.FromMinutes (Harness.LaunchTimeout))) {
|
||||
cancellation_source.Cancel ();
|
||||
main_log.WriteLine ("Test launch timed out after {0} minute(s).", Harness.LaunchTimeout);
|
||||
timed_out = true;
|
||||
} else {
|
||||
main_log.WriteLine ("Test run started");
|
||||
}
|
||||
});
|
||||
var result = await ProcessHelper.ExecuteCommandAsync (Harness.MlaunchPath, args.ToString (), run_log, TimeSpan.FromMinutes (Harness.Timeout), cancellation_token: cancellation_source.Token);
|
||||
if (result.TimedOut) {
|
||||
timed_out = true;
|
||||
|
@ -611,18 +657,15 @@ namespace xharness
|
|||
} else {
|
||||
main_log.WriteLine ("*** Executing {0}/{1} on device '{2}' ***", appName, mode, device_name);
|
||||
|
||||
args.Append (" --launchdev");
|
||||
args.AppendFormat (" \"{0}\" ", launchAppPath);
|
||||
|
||||
var waits_for_exit = false;
|
||||
if (mode == "watchos") {
|
||||
args.Append (" --attach-native-debugger"); // this prevents the watch from backgrounding the app.
|
||||
waits_for_exit = true;
|
||||
} else {
|
||||
args.Append (" --wait-for-exit");
|
||||
}
|
||||
|
||||
AddDeviceName (args);
|
||||
|
||||
device_system_log = Logs.CreateStream (LogDirectory, "device.log", "Device log");
|
||||
device_system_log = Logs.CreateStream (LogDirectory, $"device-{device_name}-{DateTime.Now:yyyyMMdd_HHmmss}.log", "Device log");
|
||||
var logdev = new DeviceLogCapturer () {
|
||||
Harness = Harness,
|
||||
Log = device_system_log,
|
||||
|
@ -632,19 +675,19 @@ namespace xharness
|
|||
|
||||
await crash_reports.StartCaptureAsync ();
|
||||
|
||||
listener.StartAsync ();
|
||||
main_log.WriteLine ("Starting test run");
|
||||
|
||||
double launch_timeout = waits_for_exit ? Harness.Timeout : 1;
|
||||
double listener_timeout = waits_for_exit ? 0.2 : Harness.Timeout;
|
||||
await ProcessHelper.ExecuteCommandAsync (Harness.MlaunchPath, args.ToString (), main_log, TimeSpan.FromMinutes (launch_timeout));
|
||||
if (listener.WaitForCompletion (TimeSpan.FromMinutes (listener_timeout))) {
|
||||
main_log.WriteLine ("Test run completed");
|
||||
} else {
|
||||
main_log.WriteLine ("Test run did not complete in {0} minutes.", Harness.Timeout);
|
||||
listener.Cancel ();
|
||||
success = false;
|
||||
var result = await ProcessHelper.ExecuteCommandAsync (Harness.MlaunchPath, args.ToString (), main_log, TimeSpan.FromMinutes (Harness.Timeout), cancellation_token: cancellation_source.Token);
|
||||
if (result.TimedOut) {
|
||||
timed_out = true;
|
||||
success = false;
|
||||
main_log.WriteLine ("Test run timed out after {0} minute(s).", Harness.Timeout);
|
||||
} else if (result.Succeeded) {
|
||||
main_log.WriteLine ("Test run completed");
|
||||
success = true;
|
||||
} else {
|
||||
main_log.WriteLine ("Test run failed");
|
||||
success = false;
|
||||
}
|
||||
|
||||
logdev.StopCapture ();
|
||||
|
|
|
@ -51,6 +51,30 @@ namespace xharness
|
|||
case null:
|
||||
case "":
|
||||
return AppRunnerTarget.None;
|
||||
default:
|
||||
throw new NotImplementedException (@this);
|
||||
}
|
||||
}
|
||||
|
||||
public static Extension ParseFromNSExtensionPointIdentifier (this string @this)
|
||||
{
|
||||
switch (@this) {
|
||||
case "com.apple.widget-extension":
|
||||
return Extension.TodayExtension;
|
||||
case "com.apple.watchkit":
|
||||
return Extension.WatchKit2;
|
||||
default:
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
}
|
||||
|
||||
public static string AsNSExtensionPointIdentifier (this Extension @this)
|
||||
{
|
||||
switch (@this) {
|
||||
case Extension.TodayExtension:
|
||||
return "com.apple.widget-extension";
|
||||
case Extension.WatchKit2:
|
||||
return "com.apple.watchkit";
|
||||
default:
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
|
|
@ -49,6 +49,8 @@ namespace xharness
|
|||
public string WatchOSContainerTemplate { get; set; }
|
||||
public string WatchOSAppTemplate { get; set; }
|
||||
public string WatchOSExtensionTemplate { get; set; }
|
||||
public string TodayContainerTemplate { get; set; }
|
||||
public string TodayExtensionTemplate { get; set; }
|
||||
public string MONO_PATH { get; set; } // Use same name as in Makefiles, so that a grep finds it.
|
||||
public string WATCH_MONO_PATH { get; set; } // Use same name as in Makefiles, so that a grep finds it.
|
||||
public string TVOS_MONO_PATH { get; set; } // Use same name as in Makefiles, so that a grep finds it.
|
||||
|
@ -282,6 +284,9 @@ namespace xharness
|
|||
WatchOSContainerTemplate = Path.GetFullPath (Path.Combine (RootDirectory, "templates/WatchContainer"));
|
||||
WatchOSAppTemplate = Path.GetFullPath (Path.Combine (RootDirectory, "templates/WatchApp"));
|
||||
WatchOSExtensionTemplate = Path.GetFullPath (Path.Combine (RootDirectory, "templates/WatchExtension"));
|
||||
|
||||
TodayContainerTemplate = Path.GetFullPath (Path.Combine (RootDirectory, "templates", "TodayContainer"));
|
||||
TodayExtensionTemplate = Path.GetFullPath (Path.Combine (RootDirectory, "templates", "TodayExtension"));
|
||||
}
|
||||
|
||||
Dictionary<string, string> make_config = new Dictionary<string, string> ();
|
||||
|
@ -399,6 +404,7 @@ namespace xharness
|
|||
var unified_targets = new List<UnifiedTarget> ();
|
||||
var tvos_targets = new List<TVOSTarget> ();
|
||||
var watchos_targets = new List<WatchOSTarget> ();
|
||||
var today_targets = new List<TodayExtensionTarget> ();
|
||||
|
||||
RootDirectory = Path.GetFullPath (RootDirectory).TrimEnd ('/');
|
||||
|
||||
|
@ -432,11 +438,20 @@ namespace xharness
|
|||
};
|
||||
unified.Execute ();
|
||||
unified_targets.Add (unified);
|
||||
|
||||
var today = new TodayExtensionTarget
|
||||
{
|
||||
TemplateProjectPath = file,
|
||||
Harness = this,
|
||||
};
|
||||
today.Execute ();
|
||||
today_targets.Add (today);
|
||||
}
|
||||
|
||||
SolutionGenerator.CreateSolution (this, watchos_targets, "watchos");
|
||||
SolutionGenerator.CreateSolution (this, tvos_targets, "tvos");
|
||||
MakefileGenerator.CreateMakefile (this, unified_targets, tvos_targets, watchos_targets);
|
||||
SolutionGenerator.CreateSolution (this, today_targets, "today");
|
||||
MakefileGenerator.CreateMakefile (this, unified_targets, tvos_targets, watchos_targets, today_targets);
|
||||
}
|
||||
|
||||
public int Install ()
|
||||
|
@ -450,9 +465,9 @@ namespace xharness
|
|||
ProjectFile = project.Path,
|
||||
MainLog = HarnessLog,
|
||||
};
|
||||
var rv = runner.Install (HarnessLog);
|
||||
if (rv != 0)
|
||||
return rv;
|
||||
var rv = runner.InstallAsync ().Result;
|
||||
if (!rv.Succeeded)
|
||||
return rv.ExitCode;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -469,9 +484,9 @@ namespace xharness
|
|||
ProjectFile = project.Path,
|
||||
MainLog = HarnessLog,
|
||||
};
|
||||
var rv = runner.Uninstall (HarnessLog);
|
||||
if (rv != 0)
|
||||
return rv;
|
||||
var rv = runner.UninstallAsync ().Result;
|
||||
if (!rv.Succeeded)
|
||||
return rv.ExitCode;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -241,7 +241,25 @@ namespace xharness
|
|||
writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi");
|
||||
}
|
||||
|
||||
public static void CreateMakefile (Harness harness, IEnumerable<UnifiedTarget> unified_targets, IEnumerable<TVOSTarget> tvos_targets, IEnumerable<WatchOSTarget> watchos_targets)
|
||||
static string GetMakeSuffix (this Target target, bool escape = true)
|
||||
{
|
||||
var rv = "-" + target.Platform;
|
||||
if (escape)
|
||||
rv = rv.Replace (" ", "\\ ");
|
||||
return rv;
|
||||
}
|
||||
|
||||
static string GetMakeName (this Target target, bool escape = true)
|
||||
{
|
||||
var rv = target.Name;
|
||||
if (escape)
|
||||
rv = rv.Replace (" ", "\\ ");
|
||||
if (target is TodayExtensionTarget)
|
||||
rv = rv + "-today";
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static void CreateMakefile (Harness harness, IEnumerable<UnifiedTarget> unified_targets, IEnumerable<TVOSTarget> tvos_targets, IEnumerable<WatchOSTarget> watchos_targets, IEnumerable<TodayExtensionTarget> today_targets)
|
||||
{
|
||||
var makefile = Path.Combine (harness.RootDirectory, "Makefile.inc");
|
||||
using (var writer = new StreamWriter (makefile, false, new UTF8Encoding (false))) {
|
||||
|
@ -254,14 +272,18 @@ namespace xharness
|
|||
allTargets.AddRange (unified_targets);
|
||||
allTargets.AddRange (tvos_targets);
|
||||
allTargets.AddRange (watchos_targets);
|
||||
allTargets.AddRange (today_targets);
|
||||
|
||||
// build/[install/]run targets for specific test projects.
|
||||
foreach (var target in allTargets) {
|
||||
if (!target.IsExe)
|
||||
continue;
|
||||
|
||||
var make_escaped_suffix = "-" + target.Platform.Replace (" ", "\\ ");
|
||||
var make_escaped_name = target.Name.Replace (" ", "\\ ");
|
||||
|
||||
var make_escaped_suffix = target.GetMakeSuffix ();
|
||||
var make_escaped_name = target.GetMakeName ();
|
||||
|
||||
if (target is TodayExtensionTarget)
|
||||
make_escaped_name += "-today";
|
||||
|
||||
writer.WriteLine ();
|
||||
if (target.ProjectPath != target.TemplateProjectPath) {
|
||||
|
@ -547,8 +569,8 @@ namespace xharness
|
|||
if (!target.IsExe)
|
||||
continue;
|
||||
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-sim-{1}\" || echo \"run{0}-sim-{1} failed\" >> \".$@-failure.stamp\"", target.Suffix, target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-dev-{1}\" || echo \"run{0}-dev-{1} failed\" >> \".$@-failure.stamp\"", target.Suffix, target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-sim-{1}\" || echo \"run{0}-sim-{1} failed\" >> \".$@-failure.stamp\"", target.GetMakeSuffix (false), target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-dev-{1}\" || echo \"run{0}-dev-{1} failed\" >> \".$@-failure.stamp\"", target.GetMakeSuffix (false), target.GetMakeName (false));
|
||||
}
|
||||
writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi");
|
||||
|
||||
|
@ -559,7 +581,7 @@ namespace xharness
|
|||
if (!target.IsExe)
|
||||
continue;
|
||||
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-sim-{1}\" || echo \"run{0}-sim-{1} failed\" >> \".$@-failure.stamp\"", target.Suffix, target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-sim-{1}\" || echo \"run{0}-sim-{1} failed\" >> \".$@-failure.stamp\"", target.GetMakeSuffix (false), target.GetMakeName (false));
|
||||
}
|
||||
writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi");
|
||||
|
||||
|
@ -570,7 +592,7 @@ namespace xharness
|
|||
if (!target.IsExe)
|
||||
continue;
|
||||
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-dev-{1}\" || echo \"run{0}-dev-{1} failed\" >> \".$@-failure.stamp\"", target.Suffix, target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"run{0}-dev-{1}\" || echo \"run{0}-dev-{1} failed\" >> \".$@-failure.stamp\"", target.GetMakeSuffix (false), target.GetMakeName (false));
|
||||
}
|
||||
writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi");
|
||||
|
||||
|
@ -587,7 +609,7 @@ namespace xharness
|
|||
if (!target.IsExe)
|
||||
continue;
|
||||
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"build-sim-{0}\" \"build-dev-{0}\" || echo \"build-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"build-sim-{0}\" \"build-dev-{0}\" || echo \"build-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
}
|
||||
writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi");
|
||||
|
||||
|
@ -596,7 +618,7 @@ namespace xharness
|
|||
foreach (var target in unified_targets) {
|
||||
if (!target.IsExe)
|
||||
continue;
|
||||
var make_escaped_name = target.Name.Replace (" ", "\\ ");
|
||||
var make_escaped_name = target.GetMakeName ();
|
||||
|
||||
writer.WriteTarget ("build-sim-{0}", "build-ios-sim-{0} build-tvos-sim-{0} build-watchos-sim-{0}", make_escaped_name);
|
||||
writer.WriteLine ("\t$(Q) echo Simulator builds succeeded"); // This is important, otherwise we'll end up executing the catch-all build-% target
|
||||
|
@ -611,36 +633,36 @@ namespace xharness
|
|||
writer.WriteLine ();
|
||||
|
||||
writer.WriteTarget ("run-sim-{0}", "build-sim-{0}", make_escaped_name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-sim32-{0}\" || echo \"exec-ios-sim32-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-sim64-{0}\" || echo \"exec-ios-sim64-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-tvos-sim-{0}\" || echo \"exec-tvos-sim-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-watchos-sim-{0}\" || echo \"exec-watchos-sim-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-sim32-{0}\" || echo \"exec-ios-sim32-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-sim64-{0}\" || echo \"exec-ios-sim64-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-tvos-sim-{0}\" || echo \"exec-tvos-sim-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-watchos-sim-{0}\" || echo \"exec-watchos-sim-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi");
|
||||
writer.WriteLine ();
|
||||
|
||||
writer.WriteTarget ("run-dev-{0}", "build-dev-{0}", make_escaped_name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"install-ios-dev-{0}\" || echo \"install-ios-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-dev-{0}\" || echo \"exec-ios-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"install-tvos-dev-{0}\" || echo \"install-tvos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-tvos-dev-{0}\" || echo \"exec-tvos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"install-watchos-dev-{0}\" || echo \"install-watchos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-watchos-dev-{0}\" || echo \"exec-watchos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"install-ios-dev-{0}\" || echo \"install-ios-dev-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-dev-{0}\" || echo \"exec-ios-dev-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"install-tvos-dev-{0}\" || echo \"install-tvos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-tvos-dev-{0}\" || echo \"exec-tvos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"install-watchos-dev-{0}\" || echo \"install-watchos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-watchos-dev-{0}\" || echo \"exec-watchos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi");
|
||||
writer.WriteLine ();
|
||||
|
||||
writer.WriteTarget ("run-{0}", "build-{0}", make_escaped_name);
|
||||
// sim
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-sim32-{0}\" || echo \"exec-ios-sim32-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-sim64-{0}\" || echo \"exec-ios-sim64-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-tvos-sim-{0}\" || echo \"exec-tvos-sim-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-watchos-sim-{0}\" || echo \"exec-watchos-sim-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-sim32-{0}\" || echo \"exec-ios-sim32-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-sim64-{0}\" || echo \"exec-ios-sim64-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-tvos-sim-{0}\" || echo \"exec-tvos-sim-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-watchos-sim-{0}\" || echo \"exec-watchos-sim-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
// dev
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"install-ios-dev-{0}\" || echo \"install-ios-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-dev-{0}\" || echo \"exec-ios-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"install-tvos-dev-{0}\" || echo \"install-tvos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-tvos-dev-{0}\" || echo \"exec-tvos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"install-watchos-dev-{0}\" || echo \"install-watchos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-watchos-dev-{0}\" || echo \"exec-watchos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"install-ios-dev-{0}\" || echo \"install-ios-dev-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-ios-dev-{0}\" || echo \"exec-ios-dev-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"install-tvos-dev-{0}\" || echo \"install-tvos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-tvos-dev-{0}\" || echo \"exec-tvos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"install-watchos-dev-{0}\" || echo \"install-watchos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"exec-watchos-dev-{0}\" || echo \"exec-watchos-dev-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi");
|
||||
writer.WriteLine ();
|
||||
|
||||
|
@ -652,19 +674,19 @@ namespace xharness
|
|||
writer.WriteLine ("\t$(Q) rm -f \".$@-failure.stamp\" \".$@-ios-sim-build-failure.stamp\" \".$@-tvos-sim-build-failure.stamp\" \".$@-watchos-sim-build-failure.stamp\"");
|
||||
writer.WriteLine ("\t$(Q) echo \"@MonkeyWrench: SetSummary:\"");
|
||||
// first build (serialized)
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"build-ios-sim-{0}\" || echo \"@MonkeyWrench: AddSummary: <b>ios failed to build</b> <br/>\" >> \".$@-ios-sim-build-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"build-tvos-sim-{0}\" || echo \"@MonkeyWrench: AddSummary: <b>tvos failed to build</b> <br/>\" >> \".$@-tvos-sim-build-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"build-ios-sim-{0}\" || echo \"@MonkeyWrench: AddSummary: <b>ios failed to build</b> <br/>\" >> \".$@-ios-sim-build-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"build-tvos-sim-{0}\" || echo \"@MonkeyWrench: AddSummary: <b>tvos failed to build</b> <br/>\" >> \".$@-tvos-sim-build-failure.stamp\"", target.GetMakeName (false));
|
||||
if (harness.INCLUDE_WATCH)
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"build-watchos-sim-{0}\" || echo \"@MonkeyWrench: AddSummary: <b>watchos failed to build</b> <br/>\" >> \".$@-watchos-sim-build-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) $(MAKE) \"build-watchos-sim-{0}\" || echo \"@MonkeyWrench: AddSummary: <b>watchos failed to build</b> <br/>\" >> \".$@-watchos-sim-build-failure.stamp\"", target.GetMakeName (false));
|
||||
// then run
|
||||
writer.WriteLine ("\t$(Q) (test -e \".$@-ios-sim-build-failure.stamp\" && cat \".$@-ios-sim-build-failure.stamp\" >> \".$@-failure.stamp\") || $(MAKE) \"exec-ios-sim32-{0}\" || echo \"exec-ios-sim32-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) test -e \".$@-ios-sim-build-failure.stamp\" || $(MAKE) \"exec-ios-sim64-{0}\" || echo \"exec-ios-sim64-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) (test -e \".$@-tvos-sim-build-failure.stamp\" && cat \".$@-tvos-sim-build-failure.stamp\" >> \".$@-failure.stamp\") || $(MAKE) \"exec-tvos-sim-{0}\" || echo \"exec-tvos-sim-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) (test -e \".$@-ios-sim-build-failure.stamp\" && cat \".$@-ios-sim-build-failure.stamp\" >> \".$@-failure.stamp\") || $(MAKE) \"exec-ios-sim32-{0}\" || echo \"exec-ios-sim32-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) test -e \".$@-ios-sim-build-failure.stamp\" || $(MAKE) \"exec-ios-sim64-{0}\" || echo \"exec-ios-sim64-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
writer.WriteLine ("\t$(Q) (test -e \".$@-tvos-sim-build-failure.stamp\" && cat \".$@-tvos-sim-build-failure.stamp\" >> \".$@-failure.stamp\") || $(MAKE) \"exec-tvos-sim-{0}\" || echo \"exec-tvos-sim-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
if (harness.INCLUDE_WATCH) {
|
||||
if (harness.DisableWatchOSOnWrench) {
|
||||
writer.WriteLine ("\t$(Q) (test -e \".$@-watchos-sim-build-failure.stamp\" && cat \".$@-watchos-sim-build-failure.stamp\" ) || $(MAKE) \"exec-watchos-sim-{0}\" || echo \"exec-watchos-sim-{0} failed\" ", target.Name);
|
||||
writer.WriteLine ("\t$(Q) (test -e \".$@-watchos-sim-build-failure.stamp\" && cat \".$@-watchos-sim-build-failure.stamp\" ) || $(MAKE) \"exec-watchos-sim-{0}\" || echo \"exec-watchos-sim-{0} failed\" ", target.GetMakeName (false));
|
||||
} else {
|
||||
writer.WriteLine ("\t$(Q) (test -e \".$@-watchos-sim-build-failure.stamp\" && cat \".$@-watchos-sim-build-failure.stamp\" >> \".$@-failure.stamp\") || $(MAKE) \"exec-watchos-sim-{0}\" || echo \"exec-watchos-sim-{0} failed\" >> \".$@-failure.stamp\"", target.Name);
|
||||
writer.WriteLine ("\t$(Q) (test -e \".$@-watchos-sim-build-failure.stamp\" && cat \".$@-watchos-sim-build-failure.stamp\" >> \".$@-failure.stamp\") || $(MAKE) \"exec-watchos-sim-{0}\" || echo \"exec-watchos-sim-{0} failed\" >> \".$@-failure.stamp\"", target.GetMakeName (false));
|
||||
}
|
||||
}
|
||||
writer.WriteLine ("\t$(Q) if test -e \".$@-failure.stamp\"; then cat \".$@-failure.stamp\"; rm \".$@-failure.stamp\"; exit 1; fi");
|
||||
|
|
|
@ -50,6 +50,11 @@ namespace xharness
|
|||
return GetPListStringValue (plist, "CFBundleIdentifier");
|
||||
}
|
||||
|
||||
public static string GetNSExtensionPointIdentifier (this XmlDocument plist)
|
||||
{
|
||||
return plist.SelectSingleNode ("//dict/key[text()='NSExtensionPointIdentifier']")?.NextSibling?.InnerText;
|
||||
}
|
||||
|
||||
public static string GetPListStringValue (this XmlDocument plist, string node)
|
||||
{
|
||||
return plist.SelectSingleNode ("//dict/key[text()='" + node + "']").NextSibling.InnerText;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
|
||||
namespace xharness
|
||||
|
@ -80,16 +82,20 @@ namespace xharness
|
|||
throw new Exception ("Could not find a condition attribute.");
|
||||
}
|
||||
|
||||
public static void SetOutputPath (this XmlDocument csproj, string value)
|
||||
public static void SetOutputPath (this XmlDocument csproj, string value, bool expand = true)
|
||||
{
|
||||
var nodes = csproj.SelectNodes ("/*/*/*[local-name() = 'OutputPath']");
|
||||
if (nodes.Count == 0)
|
||||
throw new Exception ("Could not find node OutputPath");
|
||||
foreach (XmlNode n in nodes) {
|
||||
// OutputPath needs to be expanded, otherwise Xamarin Studio isn't able to launch the project.
|
||||
string platform, configuration;
|
||||
ParseConditions (n, out platform, out configuration);
|
||||
n.InnerText = value.Replace ("$(Platform)", platform).Replace ("$(Configuration)", configuration);
|
||||
if (expand) {
|
||||
// OutputPath needs to be expanded, otherwise Xamarin Studio isn't able to launch the project.
|
||||
string platform, configuration;
|
||||
ParseConditions (n, out platform, out configuration);
|
||||
n.InnerText = value.Replace ("$(Platform)", platform).Replace ("$(Configuration)", configuration);
|
||||
} else {
|
||||
n.InnerText = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,6 +243,21 @@ namespace xharness
|
|||
item_group.AppendChild (node);
|
||||
}
|
||||
|
||||
public static void FixCompileInclude (this XmlDocument csproj, string include, string newInclude)
|
||||
{
|
||||
csproj.SelectSingleNode ($"//*[local-name() = 'Compile' and @Include = '{include}']").Attributes ["Include"].Value = newInclude;
|
||||
}
|
||||
|
||||
public static void AddInterfaceDefinition (this XmlDocument csproj, string include)
|
||||
{
|
||||
var itemGroup = csproj.CreateItemGroup ();
|
||||
var id = csproj.CreateElement ("InterfaceDefinition", MSBuild_Namespace);
|
||||
var attrib = csproj.CreateAttribute ("Include");
|
||||
attrib.Value = include;
|
||||
id.Attributes.Append (attrib);
|
||||
itemGroup.AppendChild (id);
|
||||
}
|
||||
|
||||
public static void SetImport (this XmlDocument csproj, string value)
|
||||
{
|
||||
var imports = csproj.SelectNodes ("/*/*[local-name() = 'Import']");
|
||||
|
@ -282,6 +303,18 @@ namespace xharness
|
|||
}
|
||||
}
|
||||
|
||||
public static string GetExtraMtouchArgs (this XmlDocument csproj, string platform, string configuration)
|
||||
{
|
||||
var mtouchExtraArgs = csproj.SelectNodes ("//*[local-name() = 'MtouchExtraArgs']");
|
||||
foreach (XmlNode mea in mtouchExtraArgs) {
|
||||
if (!IsNodeApplicable (mea, platform, configuration))
|
||||
continue;
|
||||
return mea.InnerText;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public static void SetMtouchUseLlvm (this XmlDocument csproj, bool value, string platform, string configuration)
|
||||
{
|
||||
SetNode (csproj, "MtouchUseLlvm", true ? "true" : "false", platform, configuration);
|
||||
|
@ -294,7 +327,7 @@ namespace xharness
|
|||
|
||||
public static void SetNode (this XmlDocument csproj, string node, string value, string platform, string configuration)
|
||||
{
|
||||
var projnode = csproj.SelectNodes ("//*[local-name() = '" + node + "']");
|
||||
var projnode = csproj.SelectElementNodes (node);
|
||||
var found = false;
|
||||
foreach (XmlNode xmlnode in projnode) {
|
||||
if (!IsNodeApplicable (xmlnode, platform, configuration))
|
||||
|
@ -420,9 +453,12 @@ namespace xharness
|
|||
{
|
||||
var import = csproj.SelectSingleNode ("/*/*/*[local-name() = 'None' and @Include = 'Info.plist']");
|
||||
import.Attributes ["Include"].Value = "Info" + suffix + ".plist";
|
||||
var logicalName = csproj.CreateElement ("LogicalName", MSBuild_Namespace);
|
||||
var logicalName = import.SelectSingleNode ("./*[local-name() = 'LogicalName']");
|
||||
if (logicalName == null) {
|
||||
logicalName = csproj.CreateElement ("LogicalName", MSBuild_Namespace);
|
||||
import.AppendChild (logicalName);
|
||||
}
|
||||
logicalName.InnerText = "Info.plist";
|
||||
import.AppendChild (logicalName);
|
||||
}
|
||||
|
||||
public static string GetInfoPListInclude (this XmlDocument csproj)
|
||||
|
@ -439,12 +475,42 @@ namespace xharness
|
|||
throw new Exception ("Could not find Info.plist include");
|
||||
}
|
||||
|
||||
public static IEnumerable<string> GetProjectReferences (this XmlDocument csproj)
|
||||
{
|
||||
var nodes = csproj.SelectNodes ("//*[local-name() = 'ProjectReference']");
|
||||
foreach (XmlNode node in nodes)
|
||||
yield return node.Attributes ["Include"].Value;
|
||||
}
|
||||
|
||||
public static IEnumerable<string> GetExtensionProjectReferences (this XmlDocument csproj)
|
||||
{
|
||||
var nodes = csproj.SelectNodes ("//*[local-name() = 'ProjectReference']");
|
||||
foreach (XmlNode node in nodes) {
|
||||
if (node.SelectSingleNode ("./*[local-name () = 'IsAppExtension']") != null)
|
||||
yield return node.Attributes ["Include"].Value;
|
||||
}
|
||||
}
|
||||
public static void SetProjectReferenceValue (this XmlDocument csproj, string projectInclude, string node, string value)
|
||||
{
|
||||
var nameNode = csproj.SelectSingleNode ("//*[local-name() = 'ProjectReference' and @Include = '" + projectInclude + "']/*[local-name() = '" + node + "']");
|
||||
nameNode.InnerText = value;
|
||||
}
|
||||
|
||||
public static void SetProjectReferenceInclude (this XmlDocument csproj, string projectInclude, string value)
|
||||
{
|
||||
var elements = csproj.SelectElementNodes ("ProjectReference");
|
||||
elements
|
||||
.Where ((v) =>
|
||||
{
|
||||
var attrib = v.Attributes ["Include"];
|
||||
if (attrib == null)
|
||||
return false;
|
||||
return attrib.Value == projectInclude;
|
||||
})
|
||||
.Single ()
|
||||
.Attributes ["Include"].Value = value;
|
||||
}
|
||||
|
||||
public static void CreateProjectReferenceValue (this XmlDocument csproj, string existingInclude, string path, string guid, string name)
|
||||
{
|
||||
var referenceNode = csproj.SelectSingleNode ("//*[local-name() = 'Reference' and @Include = '" + existingInclude + "']");
|
||||
|
@ -470,6 +536,14 @@ namespace xharness
|
|||
itemGroup.AppendChild (projectReferenceNode);
|
||||
}
|
||||
|
||||
static XmlNode CreateItemGroup (this XmlDocument csproj)
|
||||
{
|
||||
var lastItemGroup = csproj.SelectSingleNode ("//*[local-name() = 'ItemGroup'][last()]");
|
||||
var newItemGroup = csproj.CreateElement ("ItemGroup", MSBuild_Namespace);
|
||||
lastItemGroup.ParentNode.InsertAfter (newItemGroup, lastItemGroup);
|
||||
return newItemGroup;
|
||||
}
|
||||
|
||||
public static void AddAdditionalDefines (this XmlDocument csproj, string value)
|
||||
{
|
||||
var mainPropertyGroup = csproj.SelectSingleNode ("//*[local-name() = 'PropertyGroup' and not(@Condition)]");
|
||||
|
@ -544,6 +618,97 @@ namespace xharness
|
|||
|
||||
throw new Exception ("Configuration not found.");
|
||||
}
|
||||
|
||||
static IEnumerable<XmlNode> SelectElementNodes (this XmlNode node, string name)
|
||||
{
|
||||
foreach (XmlNode child in node.ChildNodes) {
|
||||
if (child.NodeType == XmlNodeType.Element && child.Name == name)
|
||||
yield return child;
|
||||
|
||||
if (!child.HasChildNodes)
|
||||
continue;
|
||||
|
||||
foreach (XmlNode descendent in child.SelectElementNodes (name))
|
||||
yield return descendent;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ResolveAllPaths (this XmlDocument csproj, string project_path)
|
||||
{
|
||||
var dir = System.IO.Path.GetDirectoryName (project_path);
|
||||
var nodes_with_paths = new string []
|
||||
{
|
||||
"AssemblyOriginatorKeyFile",
|
||||
"CodesignEntitlements",
|
||||
"TestLibrariesDirectory",
|
||||
};
|
||||
var attributes_with_paths = new string [] []
|
||||
{
|
||||
new string [] { "None", "Include" },
|
||||
new string [] { "Compile", "Include" },
|
||||
new string [] { "ProjectReference", "Include" },
|
||||
new string [] { "InterfaceDefinition", "Include" },
|
||||
new string [] { "BundleResource", "Include" },
|
||||
new string [] { "EmbeddedResource", "Include" },
|
||||
new string [] { "ImageAsset", "Include" },
|
||||
new string [] { "GeneratedTestInput", "Include" },
|
||||
new string [] { "GeneratedTestOutput", "Include" },
|
||||
new string [] { "TestLibrariesInput", "Include" },
|
||||
new string [] { "TestLibrariesOutput", "Include" },
|
||||
new string [] { "TestLibrariesOutput", "Include" },
|
||||
new string [] { "Content", "Include" },
|
||||
new string [] { "ObjcBindingApiDefinition", "Include" },
|
||||
new string [] { "ObjcBindingCoreSource", "Include" },
|
||||
new string [] { "ObjcBindingNativeLibrary", "Include" },
|
||||
new string [] { "ObjcBindingNativeFramework", "Include" },
|
||||
};
|
||||
Func<string, string> convert = (input) =>
|
||||
{
|
||||
if (input [0] == '/')
|
||||
return input; // This is already a full path.
|
||||
input = input.Replace ('\\', '/'); // make unix-style
|
||||
input = System.IO.Path.GetFullPath (System.IO.Path.Combine (dir, input));
|
||||
input = input.Replace ('/', '\\'); // make windows-style again
|
||||
return input;
|
||||
};
|
||||
|
||||
foreach (var key in nodes_with_paths) {
|
||||
|
||||
var nodes = csproj.SelectElementNodes (key);
|
||||
foreach (var node in nodes)
|
||||
node.InnerText = convert (node.InnerText);
|
||||
}
|
||||
foreach (var kvp in attributes_with_paths) {
|
||||
var element = kvp [0];
|
||||
var attrib = kvp [1];
|
||||
var nodes = csproj.SelectElementNodes (element);
|
||||
foreach (XmlNode node in nodes) {
|
||||
var a = node.Attributes [attrib];
|
||||
if (a == null)
|
||||
continue;
|
||||
// Fix any default LogicalName values (but don't change existing ones).
|
||||
var ln = node.SelectElementNodes ("LogicalName")?.SingleOrDefault ();
|
||||
var links = node.SelectElementNodes ("Link");
|
||||
if (ln == null && !links.Any ()) {
|
||||
ln = csproj.CreateElement ("LogicalName", MSBuild_Namespace);
|
||||
node.AppendChild (ln);
|
||||
|
||||
string logicalName = a.Value;
|
||||
switch (element) {
|
||||
case "BundleResource":
|
||||
if (logicalName.StartsWith ("Resources\\", StringComparison.Ordinal))
|
||||
logicalName = logicalName.Substring ("Resources\\".Length);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ln.InnerText = logicalName;
|
||||
}
|
||||
|
||||
a.Value = convert (a.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
@ -12,73 +13,93 @@ namespace xharness
|
|||
{
|
||||
public Harness Harness;
|
||||
|
||||
public List<SimRuntime> SupportedRuntimes = new List<SimRuntime> ();
|
||||
public List<SimDeviceType> SupportedDeviceTypes = new List<SimDeviceType> ();
|
||||
public List<SimDevice> AvailableDevices = new List<SimDevice> ();
|
||||
public List<SimDevicePair> AvailableDevicePairs = new List<SimDevicePair> ();
|
||||
bool loaded;
|
||||
|
||||
public async Task LoadAsync (Log log)
|
||||
BlockingEnumerableCollection<SimRuntime> supported_runtimes = new BlockingEnumerableCollection<SimRuntime> ();
|
||||
BlockingEnumerableCollection<SimDeviceType> supported_device_types = new BlockingEnumerableCollection<SimDeviceType> ();
|
||||
BlockingEnumerableCollection<SimDevice> available_devices = new BlockingEnumerableCollection<SimDevice> ();
|
||||
BlockingEnumerableCollection<SimDevicePair> available_device_pairs = new BlockingEnumerableCollection<SimDevicePair> ();
|
||||
|
||||
public IEnumerable<SimRuntime> SupportedRuntimes => supported_runtimes;
|
||||
public IEnumerable<SimDeviceType> SupportedDeviceTypes => supported_device_types;
|
||||
public IEnumerable<SimDevice> AvailableDevices => available_devices;
|
||||
public IEnumerable<SimDevicePair> AvailableDevicePairs => available_device_pairs;
|
||||
|
||||
public Task LoadAsync (Log log)
|
||||
{
|
||||
if (SupportedRuntimes.Count > 0)
|
||||
return;
|
||||
|
||||
var tmpfile = Path.GetTempFileName ();
|
||||
try {
|
||||
using (var process = new Process ()) {
|
||||
process.StartInfo.FileName = Harness.MlaunchPath;
|
||||
process.StartInfo.Arguments = string.Format ("--sdkroot {0} --listsim {1}", Harness.XcodeRoot, tmpfile);
|
||||
log.WriteLine ("Launching {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
||||
var rv = await process.RunAsync (log, false);
|
||||
if (!rv.Succeeded)
|
||||
throw new Exception ("Failed to list simulators.");
|
||||
log.WriteLine ("Result:");
|
||||
log.WriteLine (File.ReadAllText (tmpfile));
|
||||
var simulator_data = new XmlDocument ();
|
||||
simulator_data.LoadWithoutNetworkAccess (tmpfile);
|
||||
foreach (XmlNode sim in simulator_data.SelectNodes ("/MTouch/Simulator/SupportedRuntimes/SimRuntime")) {
|
||||
SupportedRuntimes.Add (new SimRuntime ()
|
||||
{
|
||||
Name = sim.SelectSingleNode ("Name").InnerText,
|
||||
Identifier = sim.SelectSingleNode ("Identifier").InnerText,
|
||||
Version = long.Parse (sim.SelectSingleNode ("Version").InnerText),
|
||||
});
|
||||
}
|
||||
foreach (XmlNode sim in simulator_data.SelectNodes ("/MTouch/Simulator/SupportedDeviceTypes/SimDeviceType")) {
|
||||
SupportedDeviceTypes.Add (new SimDeviceType ()
|
||||
{
|
||||
Name = sim.SelectSingleNode ("Name").InnerText,
|
||||
Identifier = sim.SelectSingleNode ("Identifier").InnerText,
|
||||
ProductFamilyId = sim.SelectSingleNode ("ProductFamilyId").InnerText,
|
||||
MinRuntimeVersion = long.Parse (sim.SelectSingleNode ("MinRuntimeVersion").InnerText),
|
||||
MaxRuntimeVersion = long.Parse (sim.SelectSingleNode ("MaxRuntimeVersion").InnerText),
|
||||
Supports64Bits = bool.Parse (sim.SelectSingleNode ("Supports64Bits").InnerText),
|
||||
});
|
||||
}
|
||||
foreach (XmlNode sim in simulator_data.SelectNodes ("/MTouch/Simulator/AvailableDevices/SimDevice")) {
|
||||
AvailableDevices.Add (new SimDevice ()
|
||||
{
|
||||
Harness = Harness,
|
||||
Name = sim.Attributes ["Name"].Value,
|
||||
UDID = sim.Attributes ["UDID"].Value,
|
||||
SimRuntime = sim.SelectSingleNode ("SimRuntime").InnerText,
|
||||
SimDeviceType = sim.SelectSingleNode ("SimDeviceType").InnerText,
|
||||
DataPath = sim.SelectSingleNode ("DataPath").InnerText,
|
||||
LogPath = sim.SelectSingleNode ("LogPath").InnerText,
|
||||
});
|
||||
}
|
||||
foreach (XmlNode sim in simulator_data.SelectNodes ("/MTouch/Simulator/AvailableDevicePairs/SimDevicePair")) {
|
||||
AvailableDevicePairs.Add (new SimDevicePair ()
|
||||
{
|
||||
UDID = sim.Attributes ["UDID"].Value,
|
||||
Companion = sim.SelectSingleNode ("Companion").InnerText,
|
||||
Gizmo = sim.SelectSingleNode ("Gizmo").InnerText,
|
||||
if (loaded)
|
||||
return Task.CompletedTask;
|
||||
loaded = true;
|
||||
|
||||
});
|
||||
Task.Run (async () =>
|
||||
{
|
||||
var tmpfile = Path.GetTempFileName ();
|
||||
try {
|
||||
using (var process = new Process ()) {
|
||||
process.StartInfo.FileName = Harness.MlaunchPath;
|
||||
process.StartInfo.Arguments = string.Format ("--sdkroot {0} --listsim {1}", Harness.XcodeRoot, tmpfile);
|
||||
log.WriteLine ("Launching {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
||||
var rv = await process.RunAsync (log, false);
|
||||
if (!rv.Succeeded)
|
||||
throw new Exception ("Failed to list simulators.");
|
||||
log.WriteLine ("Result:");
|
||||
log.WriteLine (File.ReadAllText (tmpfile));
|
||||
var simulator_data = new XmlDocument ();
|
||||
simulator_data.LoadWithoutNetworkAccess (tmpfile);
|
||||
foreach (XmlNode sim in simulator_data.SelectNodes ("/MTouch/Simulator/SupportedRuntimes/SimRuntime")) {
|
||||
supported_runtimes.Add (new SimRuntime ()
|
||||
{
|
||||
Name = sim.SelectSingleNode ("Name").InnerText,
|
||||
Identifier = sim.SelectSingleNode ("Identifier").InnerText,
|
||||
Version = long.Parse (sim.SelectSingleNode ("Version").InnerText),
|
||||
});
|
||||
}
|
||||
supported_runtimes.SetCompleted ();
|
||||
|
||||
foreach (XmlNode sim in simulator_data.SelectNodes ("/MTouch/Simulator/SupportedDeviceTypes/SimDeviceType")) {
|
||||
supported_device_types.Add (new SimDeviceType ()
|
||||
{
|
||||
Name = sim.SelectSingleNode ("Name").InnerText,
|
||||
Identifier = sim.SelectSingleNode ("Identifier").InnerText,
|
||||
ProductFamilyId = sim.SelectSingleNode ("ProductFamilyId").InnerText,
|
||||
MinRuntimeVersion = long.Parse (sim.SelectSingleNode ("MinRuntimeVersion").InnerText),
|
||||
MaxRuntimeVersion = long.Parse (sim.SelectSingleNode ("MaxRuntimeVersion").InnerText),
|
||||
Supports64Bits = bool.Parse (sim.SelectSingleNode ("Supports64Bits").InnerText),
|
||||
});
|
||||
}
|
||||
supported_device_types.SetCompleted ();
|
||||
|
||||
foreach (XmlNode sim in simulator_data.SelectNodes ("/MTouch/Simulator/AvailableDevices/SimDevice")) {
|
||||
available_devices.Add (new SimDevice ()
|
||||
{
|
||||
Harness = Harness,
|
||||
Name = sim.Attributes ["Name"].Value,
|
||||
UDID = sim.Attributes ["UDID"].Value,
|
||||
SimRuntime = sim.SelectSingleNode ("SimRuntime").InnerText,
|
||||
SimDeviceType = sim.SelectSingleNode ("SimDeviceType").InnerText,
|
||||
DataPath = sim.SelectSingleNode ("DataPath").InnerText,
|
||||
LogPath = sim.SelectSingleNode ("LogPath").InnerText,
|
||||
});
|
||||
}
|
||||
available_devices.SetCompleted ();
|
||||
|
||||
foreach (XmlNode sim in simulator_data.SelectNodes ("/MTouch/Simulator/AvailableDevicePairs/SimDevicePair")) {
|
||||
available_device_pairs.Add (new SimDevicePair ()
|
||||
{
|
||||
UDID = sim.Attributes ["UDID"].Value,
|
||||
Companion = sim.SelectSingleNode ("Companion").InnerText,
|
||||
Gizmo = sim.SelectSingleNode ("Gizmo").InnerText,
|
||||
|
||||
});
|
||||
}
|
||||
available_device_pairs.SetCompleted ();
|
||||
}
|
||||
} finally {
|
||||
File.Delete (tmpfile);
|
||||
}
|
||||
} finally {
|
||||
File.Delete (tmpfile);
|
||||
}
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task<SimDevice []> FindAsync (AppRunnerTarget target, Log log)
|
||||
|
@ -173,7 +194,7 @@ namespace xharness
|
|||
log.WriteLine ($"Could not create device pair, so could not find simulator for runtime={simulator_runtime} and device type={string.Join ("; ", simulator_devicetypes)}.");
|
||||
return null;
|
||||
}
|
||||
AvailableDevicePairs.Add (new SimDevicePair ()
|
||||
available_device_pairs.Add (new SimDevicePair ()
|
||||
{
|
||||
Companion = companionDevice.UDID,
|
||||
Gizmo = watchDevice.UDID,
|
||||
|
@ -201,6 +222,80 @@ namespace xharness
|
|||
|
||||
return simulators;
|
||||
}
|
||||
|
||||
public SimDevice FindCompanionDevice (Log log, SimDevice device)
|
||||
{
|
||||
var pair = available_device_pairs.Where ((v) => v.Gizmo == device.UDID).Single ();
|
||||
return available_devices.Single ((v) => v.UDID == pair.Companion);
|
||||
}
|
||||
|
||||
public IEnumerable<SimDevice> SelectDevices (AppRunnerTarget target, Log log)
|
||||
{
|
||||
return new SimulatorEnumerable
|
||||
{
|
||||
Simulators = this,
|
||||
Target = target,
|
||||
Log = log,
|
||||
};
|
||||
}
|
||||
|
||||
class SimulatorEnumerable : IEnumerable<SimDevice>
|
||||
{
|
||||
public Simulators Simulators;
|
||||
public AppRunnerTarget Target;
|
||||
public Log Log;
|
||||
|
||||
public IEnumerator<SimDevice> GetEnumerator ()
|
||||
{
|
||||
return new Enumerator ()
|
||||
{
|
||||
Enumerable = this,
|
||||
};
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator ()
|
||||
{
|
||||
return GetEnumerator ();
|
||||
}
|
||||
|
||||
class Enumerator : IEnumerator<SimDevice>
|
||||
{
|
||||
internal SimulatorEnumerable Enumerable;
|
||||
SimDevice [] devices;
|
||||
bool moved;
|
||||
|
||||
public SimDevice Current {
|
||||
get {
|
||||
return devices [0];
|
||||
}
|
||||
}
|
||||
|
||||
object IEnumerator.Current {
|
||||
get {
|
||||
return Current;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
}
|
||||
|
||||
public bool MoveNext ()
|
||||
{
|
||||
if (moved)
|
||||
return false;
|
||||
if (devices == null)
|
||||
devices = Enumerable.Simulators.FindAsync (Enumerable.Target, Enumerable.Log).Result;
|
||||
moved = true;
|
||||
return moved;
|
||||
}
|
||||
|
||||
public void Reset ()
|
||||
{
|
||||
moved = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SimRuntime
|
||||
|
@ -220,10 +315,10 @@ namespace xharness
|
|||
public bool Supports64Bits;
|
||||
}
|
||||
|
||||
public class SimDevice
|
||||
public class SimDevice : IDevice
|
||||
{
|
||||
public string UDID;
|
||||
public string Name;
|
||||
public string UDID { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string SimRuntime;
|
||||
public string SimDeviceType;
|
||||
public string DataPath;
|
||||
|
@ -384,53 +479,304 @@ namespace xharness
|
|||
public string Gizmo;
|
||||
}
|
||||
|
||||
public class SimDeviceSpecification
|
||||
{
|
||||
public SimDevice Main;
|
||||
public SimDevice Companion; // the phone for watch devices
|
||||
}
|
||||
|
||||
public class Devices
|
||||
{
|
||||
public Harness Harness;
|
||||
|
||||
public List<Device> ConnectedDevices = new List<Device> ();
|
||||
bool loaded;
|
||||
|
||||
public async Task LoadAsync (Log log)
|
||||
{
|
||||
if (ConnectedDevices.Count > 0)
|
||||
return;
|
||||
|
||||
var tmpfile = Path.GetTempFileName ();
|
||||
try {
|
||||
using (var process = new Process ()) {
|
||||
process.StartInfo.FileName = Harness.MlaunchPath;
|
||||
process.StartInfo.Arguments = string.Format ("--sdkroot {0} --listdev={1} --output-format=xml", Harness.XcodeRoot, tmpfile);
|
||||
await process.RunAsync (log, false);
|
||||
|
||||
var doc = new XmlDocument ();
|
||||
doc.LoadWithoutNetworkAccess (tmpfile);
|
||||
|
||||
foreach (XmlNode dev in doc.SelectNodes ("/MTouch/Device")) {
|
||||
ConnectedDevices.Add (new Device ()
|
||||
{
|
||||
DeviceIdentifier = dev.SelectSingleNode ("DeviceIdentifier")?.InnerText,
|
||||
DeviceClass = dev.SelectSingleNode ("DeviceClass")?.InnerText,
|
||||
CompanionIdentifier = dev.SelectSingleNode ("CompanionIdentifier")?.InnerText,
|
||||
Name = dev.SelectSingleNode ("Name")?.InnerText,
|
||||
BuildVersion = dev.SelectSingleNode ("BuildVersion")?.InnerText,
|
||||
ProductVersion = dev.SelectSingleNode ("ProductVersion")?.InnerText,
|
||||
});
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
File.Delete (tmpfile);
|
||||
BlockingEnumerableCollection<Device> connected_devices = new BlockingEnumerableCollection<Device> ();
|
||||
public IEnumerable<Device> ConnectedDevices {
|
||||
get {
|
||||
return connected_devices;
|
||||
}
|
||||
}
|
||||
|
||||
public Task LoadAsync (Log log, bool extra_data = false, bool removed_locked = false)
|
||||
{
|
||||
if (loaded)
|
||||
return Task.FromResult (true);
|
||||
loaded = true;
|
||||
|
||||
Task.Run (async () =>
|
||||
{
|
||||
var tmpfile = Path.GetTempFileName ();
|
||||
try {
|
||||
using (var process = new Process ()) {
|
||||
process.StartInfo.FileName = Harness.MlaunchPath;
|
||||
process.StartInfo.Arguments = string.Format ("--sdkroot {0} --listdev={1} {2} --output-format=xml", Harness.XcodeRoot, tmpfile, extra_data ? "--list-extra-data" : string.Empty);
|
||||
var rv = await process.RunAsync (log, false);
|
||||
if (!rv.Succeeded)
|
||||
throw new Exception ("Failed to list devices.");
|
||||
|
||||
var doc = new XmlDocument ();
|
||||
doc.LoadWithoutNetworkAccess (tmpfile);
|
||||
|
||||
foreach (XmlNode dev in doc.SelectNodes ("/MTouch/Device")) {
|
||||
Device d = new Device
|
||||
{
|
||||
DeviceIdentifier = dev.SelectSingleNode ("DeviceIdentifier")?.InnerText,
|
||||
DeviceClass = dev.SelectSingleNode ("DeviceClass")?.InnerText,
|
||||
CompanionIdentifier = dev.SelectSingleNode ("CompanionIdentifier")?.InnerText,
|
||||
Name = dev.SelectSingleNode ("Name")?.InnerText,
|
||||
BuildVersion = dev.SelectSingleNode ("BuildVersion")?.InnerText,
|
||||
ProductVersion = dev.SelectSingleNode ("ProductVersion")?.InnerText,
|
||||
ProductType = dev.SelectSingleNode ("ProductType")?.InnerText,
|
||||
};
|
||||
bool.TryParse (dev.SelectSingleNode ("IsLocked")?.InnerText, out d.IsLocked);
|
||||
if (removed_locked && d.IsLocked)
|
||||
continue;
|
||||
connected_devices.Add (d);
|
||||
}
|
||||
|
||||
connected_devices.SetCompleted ();
|
||||
}
|
||||
} finally {
|
||||
File.Delete (tmpfile);
|
||||
}
|
||||
});
|
||||
|
||||
return Task.FromResult (true);
|
||||
}
|
||||
|
||||
public Device FindCompanionDevice (Log log, Device device)
|
||||
{
|
||||
var companion = ConnectedDevices.Where ((v) => v.DeviceIdentifier == device.CompanionIdentifier);
|
||||
if (companion.Count () == 0)
|
||||
throw new Exception ($"Could not find the companion device for '{device.Name}'");
|
||||
|
||||
if (companion.Count () > 1)
|
||||
log.WriteLine ("Found {0} companion devices for {1}?!?", companion.Count (), device.Name);
|
||||
|
||||
return companion.First ();
|
||||
}
|
||||
}
|
||||
|
||||
public class Device
|
||||
public enum Architecture
|
||||
{
|
||||
ARMv6,
|
||||
ARMv7,
|
||||
ARMv7k,
|
||||
ARMv7s,
|
||||
ARM64,
|
||||
i386,
|
||||
x86_64,
|
||||
}
|
||||
|
||||
public enum DevicePlatform
|
||||
{
|
||||
iOS,
|
||||
tvOS,
|
||||
watchOS,
|
||||
}
|
||||
|
||||
public class Device : IDevice
|
||||
{
|
||||
public string DeviceIdentifier;
|
||||
public string DeviceClass;
|
||||
public string CompanionIdentifier;
|
||||
public string Name;
|
||||
public string Name { get; set; }
|
||||
public string BuildVersion;
|
||||
public string ProductVersion;
|
||||
public string ProductType;
|
||||
public bool IsLocked;
|
||||
|
||||
public string UDID { get { return DeviceIdentifier; } set { DeviceIdentifier = value; } }
|
||||
|
||||
public DevicePlatform DevicePlatform {
|
||||
get {
|
||||
switch (DeviceClass) {
|
||||
case "iPhone":
|
||||
case "iPod":
|
||||
case "iPad":
|
||||
return DevicePlatform.iOS;
|
||||
case "AppleTV":
|
||||
return DevicePlatform.tvOS;
|
||||
case "Watch":
|
||||
return DevicePlatform.watchOS;
|
||||
default:
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Supports64Bit {
|
||||
get { return Architecture == Architecture.ARM64; }
|
||||
}
|
||||
|
||||
public Architecture Architecture {
|
||||
get {
|
||||
var model = ProductType;
|
||||
|
||||
// https://www.theiphonewiki.com/wiki/Models
|
||||
if (model.StartsWith ("iPhone", StringComparison.Ordinal)) {
|
||||
var identifier = model.Substring ("iPhone".Length);
|
||||
var values = identifier.Split (',');
|
||||
|
||||
switch (values [0]) {
|
||||
case "1": // iPhone (1) and iPhone 3G (2)
|
||||
return Architecture.ARMv6;
|
||||
case "2": // iPhone 3GS (1)
|
||||
case "3": // iPhone 4 (1-3)
|
||||
case "4": // iPhone 4S (1)
|
||||
return Architecture.ARMv7;
|
||||
case "5": // iPhone 5 (1-2) and iPhone 5c (3-4)
|
||||
return Architecture.ARMv7s;
|
||||
case "6": // iPhone 5s (1-2)
|
||||
case "7": // iPhone 6+ (1) and iPhone 6 (2)
|
||||
case "8": // iPhone 6s (1), iPhone 6s+ (2), iPhoneSE (4)
|
||||
case "9": // iPhone 7 (1,3) and iPhone 7+ (2,4)
|
||||
default:
|
||||
return Architecture.ARM64;
|
||||
}
|
||||
}
|
||||
|
||||
// https://www.theiphonewiki.com/wiki/List_of_iPads
|
||||
if (model.StartsWith ("iPad", StringComparison.Ordinal)) {
|
||||
var identifier = model.Substring ("iPad".Length);
|
||||
var values = identifier.Split (',');
|
||||
|
||||
switch (values [0]) {
|
||||
case "1": // iPad (1)
|
||||
case "2": // iPad 2 (1-4) and iPad Mini (5-7)
|
||||
case "3": // iPad 3 (1-3) and iPad 4 (4-6)
|
||||
return Architecture.ARMv7;
|
||||
case "4": // iPad Air (1-3), iPad Mini 2 (4-6) and iPad Mini 3 (7-9)
|
||||
case "5": // iPad Air 2 (3-4)
|
||||
case "6": // iPad Pro 9.7-inch (3-4), iPad Pro 12.9-inch (7-8)
|
||||
default:
|
||||
return Architecture.ARM64;
|
||||
}
|
||||
}
|
||||
|
||||
// https://www.theiphonewiki.com/wiki/List_of_iPod_touches
|
||||
if (model.StartsWith ("iPod", StringComparison.Ordinal)) {
|
||||
var identifier = model.Substring ("iPod".Length);
|
||||
var values = identifier.Split (',');
|
||||
|
||||
switch (values [0]) {
|
||||
case "1": // iPod touch (1)
|
||||
case "2": // iPod touch 2G (1)
|
||||
return Architecture.ARMv6;
|
||||
case "3": // iPod touch 3G (1)
|
||||
case "4": // iPod touch 4G (1)
|
||||
case "5": // iPod touch 5G (1)
|
||||
return Architecture.ARMv7;
|
||||
case "7": // iPod touch 6G (1)
|
||||
default:
|
||||
return Architecture.ARM64;
|
||||
}
|
||||
}
|
||||
|
||||
// https://www.theiphonewiki.com/wiki/List_of_Apple_Watches
|
||||
if (model.StartsWith ("Watch", StringComparison.Ordinal))
|
||||
return Architecture.ARMv7k;
|
||||
|
||||
// https://www.theiphonewiki.com/wiki/List_of_Apple_TVs
|
||||
if (model.StartsWith ("AppleTV", StringComparison.Ordinal))
|
||||
return Architecture.ARM64;
|
||||
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface IDevice
|
||||
{
|
||||
string Name { get; set; }
|
||||
string UDID { get; set; }
|
||||
}
|
||||
|
||||
|
||||
// This is a collection whose enumerator will wait enumerating until
|
||||
// the collection has been marked as completed (but the enumerator can still
|
||||
// be created; this allows the creation of linq queries whose execution is
|
||||
// delayed until later).
|
||||
internal class BlockingEnumerableCollection<T> : IEnumerable<T> where T : class
|
||||
{
|
||||
List<T> list = new List<T> ();
|
||||
TaskCompletionSource<bool> completed = new TaskCompletionSource<bool> ();
|
||||
|
||||
public int Count {
|
||||
get {
|
||||
WaitForCompletion ();
|
||||
return list.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public void Add (T device)
|
||||
{
|
||||
if (completed.Task.IsCompleted)
|
||||
Console.WriteLine ("Adding to completed collection!");
|
||||
list.Add (device);
|
||||
}
|
||||
|
||||
public void SetCompleted ()
|
||||
{
|
||||
completed.TrySetResult (true);
|
||||
}
|
||||
|
||||
void WaitForCompletion ()
|
||||
{
|
||||
completed.Task.Wait ();
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator ()
|
||||
{
|
||||
return new Enumerator (this);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator ()
|
||||
{
|
||||
return GetEnumerator ();
|
||||
}
|
||||
|
||||
class Enumerator : IEnumerator<T>
|
||||
{
|
||||
BlockingEnumerableCollection<T> collection;
|
||||
IEnumerator<T> enumerator;
|
||||
|
||||
public Enumerator (BlockingEnumerableCollection<T> collection)
|
||||
{
|
||||
this.collection = collection;
|
||||
}
|
||||
|
||||
public T Current {
|
||||
get {
|
||||
return enumerator.Current;
|
||||
}
|
||||
}
|
||||
|
||||
object IEnumerator.Current {
|
||||
get {
|
||||
return enumerator.Current;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
enumerator.Dispose ();
|
||||
}
|
||||
|
||||
public bool MoveNext ()
|
||||
{
|
||||
collection.WaitForCompletion ();
|
||||
if (enumerator == null)
|
||||
enumerator = collection.list.GetEnumerator ();
|
||||
return enumerator.MoveNext ();
|
||||
}
|
||||
|
||||
public void Reset ()
|
||||
{
|
||||
enumerator.Reset ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -100,10 +100,17 @@ namespace xharness
|
|||
|
||||
// Add reference to MonoTouch.NUnitLite project
|
||||
string configuration;
|
||||
AddProjectToSolution (harness, sln_path, writer, Path.GetFullPath (Path.Combine (srcDirectory, "MonoTouch.NUnitLite." + infix + ".csproj")), out configuration);
|
||||
var proj_path = Path.GetFullPath (Path.Combine (srcDirectory, "MonoTouch.NUnitLite." + infix + ".csproj"));
|
||||
if (!File.Exists (proj_path))
|
||||
proj_path = Path.GetFullPath (Path.Combine (srcDirectory, "MonoTouch.NUnitLite.csproj"));
|
||||
AddProjectToSolution (harness, sln_path, writer, proj_path, out configuration);
|
||||
string configuration2 = string.Empty;
|
||||
if (infix != "watchos")
|
||||
AddProjectToSolution (harness, sln_path, writer, Path.GetFullPath (Path.Combine (srcDirectory, "MonoTouch.Dialog-1." + infix + ".csproj")), out configuration2);
|
||||
if (infix != "watchos") {
|
||||
proj_path = Path.GetFullPath (Path.Combine (srcDirectory, "MonoTouch.Dialog-1." + infix + ".csproj"));
|
||||
if (!File.Exists (proj_path))
|
||||
proj_path = Path.GetFullPath (Path.Combine (srcDirectory, "MonoTouch.Dialog-1.csproj"));
|
||||
AddProjectToSolution (harness, sln_path, writer, proj_path, out configuration2);
|
||||
}
|
||||
|
||||
writer.WriteLine ("Global");
|
||||
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace xharness
|
||||
{
|
||||
public class TestProject
|
||||
{
|
||||
XmlDocument xml;
|
||||
|
||||
public string Path;
|
||||
public bool IsExecutableProject;
|
||||
public bool GenerateVariations = true;
|
||||
|
@ -17,6 +25,97 @@ namespace xharness
|
|||
IsExecutableProject = isExecutableProject;
|
||||
GenerateVariations = generateVariations;
|
||||
}
|
||||
|
||||
public TestProject AsTvOSProject ()
|
||||
{
|
||||
var clone = Clone ();
|
||||
clone.Path = System.IO.Path.Combine (System.IO.Path.GetDirectoryName (Path), System.IO.Path.GetFileNameWithoutExtension (Path) + "-tvos" + System.IO.Path.GetExtension (Path));
|
||||
return clone;
|
||||
}
|
||||
|
||||
public TestProject AsWatchOSProject ()
|
||||
{
|
||||
var clone = Clone ();
|
||||
clone.Path = System.IO.Path.Combine (System.IO.Path.GetDirectoryName (Path), System.IO.Path.GetFileNameWithoutExtension (Path) + "-watchos" + System.IO.Path.GetExtension (Path));
|
||||
return clone;
|
||||
}
|
||||
|
||||
public TestProject AsTodayExtensionProject ()
|
||||
{
|
||||
var clone = Clone ();
|
||||
clone.Path = System.IO.Path.Combine (System.IO.Path.GetDirectoryName (Path), System.IO.Path.GetFileNameWithoutExtension (Path) + "-today" + System.IO.Path.GetExtension (Path));
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Get the referenced today extension project (if any)
|
||||
public TestProject GetTodayExtension ()
|
||||
{
|
||||
var extensions = Xml.GetExtensionProjectReferences ().ToArray ();
|
||||
if (!extensions.Any ())
|
||||
return null;
|
||||
if (extensions.Count () != 1)
|
||||
throw new NotImplementedException ();
|
||||
return new TestProject
|
||||
{
|
||||
Path = System.IO.Path.GetFullPath (System.IO.Path.Combine (System.IO.Path.GetDirectoryName (Path), extensions.First ().Replace ('\\', '/'))),
|
||||
};
|
||||
}
|
||||
|
||||
public XmlDocument Xml {
|
||||
get {
|
||||
if (xml == null) {
|
||||
xml = new XmlDocument ();
|
||||
xml.LoadWithoutNetworkAccess (Path);
|
||||
}
|
||||
return xml;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsBclTest {
|
||||
get {
|
||||
return Path.Contains ("bcl-test");
|
||||
}
|
||||
}
|
||||
|
||||
public virtual TestProject Clone ()
|
||||
{
|
||||
return new TestProject ()
|
||||
{
|
||||
Path = Path,
|
||||
IsExecutableProject = IsExecutableProject,
|
||||
GenerateVariations = GenerateVariations,
|
||||
};
|
||||
}
|
||||
|
||||
internal async Task<TestProject> CreateCloneAsync (TestTask test)
|
||||
{
|
||||
var rv = Clone ();
|
||||
await rv.CreateCopyAsync (test);
|
||||
return rv;
|
||||
}
|
||||
|
||||
internal async Task CreateCopyAsync (TestTask test)
|
||||
{
|
||||
var directory = Xamarin.Cache.CreateTemporaryDirectory (test.TestName);
|
||||
Directory.CreateDirectory (directory);
|
||||
var original_path = Path;
|
||||
Path = System.IO.Path.Combine (directory, System.IO.Path.GetFileName (Path));
|
||||
|
||||
await Task.Yield ();
|
||||
|
||||
XmlDocument doc;
|
||||
doc = new XmlDocument ();
|
||||
doc.LoadWithoutNetworkAccess (original_path);
|
||||
doc.ResolveAllPaths (original_path);
|
||||
|
||||
foreach (var pr in doc.GetProjectReferences ()) {
|
||||
var tp = new TestProject (pr.Replace ('\\', '/'));
|
||||
await tp.CreateCopyAsync (test);
|
||||
doc.SetProjectReferenceInclude (pr, tp.Path.Replace ('/', '\\'));
|
||||
}
|
||||
|
||||
doc.Save (Path);
|
||||
}
|
||||
}
|
||||
|
||||
public class MacTestProject : TestProject
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
|
||||
namespace xharness
|
||||
{
|
||||
public class TodayExtensionTarget : UnifiedTarget
|
||||
{
|
||||
public string AppName { get; private set; }
|
||||
public string ExtensionName { get; private set; }
|
||||
|
||||
public string TodayContainerGuid { get; private set; }
|
||||
public string TodayExtensionGuid { get; private set; }
|
||||
|
||||
public string TodayContainerProjectPath { get; private set; }
|
||||
public string TodayExtensionProjectPath { get; private set; }
|
||||
|
||||
public override string Suffix {
|
||||
get {
|
||||
return "-today";
|
||||
}
|
||||
}
|
||||
|
||||
public override string ProjectFileSuffix {
|
||||
get {
|
||||
return "-today";
|
||||
}
|
||||
}
|
||||
|
||||
void CreateTodayContainerProject ()
|
||||
{
|
||||
var csproj = new XmlDocument ();
|
||||
var suffix = "-today";
|
||||
csproj.LoadWithoutNetworkAccess (Path.Combine (Harness.TodayContainerTemplate, "TodayContainer.csproj"));
|
||||
csproj.SetOutputPath ("bin\\$(Platform)\\$(Configuration)" + suffix, false);
|
||||
csproj.SetIntermediateOutputPath ("obj\\$(Platform)\\$(Configuration)" + suffix);
|
||||
csproj.SetProjectReferenceValue ("TodayExtension.csproj", "Name", Path.GetFileNameWithoutExtension (TodayExtensionProjectPath));
|
||||
csproj.SetProjectReferenceValue ("TodayExtension.csproj", "Project", TodayExtensionGuid);
|
||||
csproj.SetProjectReferenceInclude ("TodayExtension.csproj", TodayExtensionProjectPath.Replace ('/', '\\'));
|
||||
csproj.FixCompileInclude ("Main.cs", Path.Combine (Harness.TodayContainerTemplate, "Main.cs").Replace ('/', '\\'));
|
||||
csproj.FixInfoPListInclude (suffix);
|
||||
TodayContainerGuid = "{" + Harness.NewStableGuid ().ToString ().ToUpper () + "}";
|
||||
csproj.SetProjectGuid (TodayContainerGuid);
|
||||
Harness.Save (csproj, TodayContainerProjectPath);
|
||||
|
||||
XmlDocument info_plist = new XmlDocument ();
|
||||
var target_info_plist = Path.Combine (TargetDirectory, "Info-today.plist");
|
||||
info_plist.LoadWithoutNetworkAccess (Path.Combine (Harness.TodayContainerTemplate, "Info.plist"));
|
||||
info_plist.SetCFBundleIdentifier (BundleIdentifier);
|
||||
info_plist.SetCFBundleName (Name);
|
||||
info_plist.SetMinimumOSVersion ("6.0");
|
||||
Harness.Save (info_plist, target_info_plist);
|
||||
}
|
||||
|
||||
void CreateTodayExtensionProject ()
|
||||
{
|
||||
var csproj = inputProject;
|
||||
var suffix = "-today-extension";
|
||||
csproj.SetProjectTypeGuids ("{FEACFBD2-3405-455C-9665-78FE426C6842};" + LanguageGuid);
|
||||
csproj.SetOutputPath ("bin\\$(Platform)\\$(Configuration)" + suffix);
|
||||
csproj.SetIntermediateOutputPath ("obj\\$(Platform)\\$(Configuration)" + suffix);
|
||||
csproj.SetImport (IsFSharp ? "$(MSBuildExtensionsPath)\\Xamarin\\iOS\\Xamarin.iOS.AppExtension.FSharp.targets" : "$(MSBuildExtensionsPath)\\Xamarin\\iOS\\Xamarin.iOS.AppExtension.CSharp.targets");
|
||||
csproj.FixInfoPListInclude (suffix);
|
||||
csproj.SetOutputType ("Library");
|
||||
csproj.AddAdditionalDefines ("XAMCORE_2_0;XAMCORE_3_0");
|
||||
var ext = IsFSharp ? "fs" : "cs";
|
||||
csproj.AddCompileInclude ("Main." + ext, Path.Combine (Harness.TodayExtensionTemplate, "Main." + ext));
|
||||
csproj.AddInterfaceDefinition (Path.Combine (Harness.TodayExtensionTemplate, "TodayView.storyboard").Replace ('/', '\\'));
|
||||
csproj.SetExtraLinkerDefs ("extra-linker-defs" + Suffix + ".xml");
|
||||
|
||||
Harness.Save (csproj, TodayExtensionProjectPath);
|
||||
|
||||
TodayExtensionGuid = csproj.GetProjectGuid ();
|
||||
|
||||
XmlDocument info_plist = new XmlDocument ();
|
||||
var target_info_plist = Path.Combine (TargetDirectory, "Info-today-extension.plist");
|
||||
info_plist.LoadWithoutNetworkAccess (Path.Combine (TargetDirectory, "Info.plist"));
|
||||
BundleIdentifier = info_plist.GetCFBundleIdentifier () + "-today";
|
||||
info_plist.SetCFBundleIdentifier (BundleIdentifier + ".todayextension");
|
||||
info_plist.SetMinimumOSVersion ("8.0");
|
||||
info_plist.AddPListStringValue ("CFBundlePackageType", "XPC!");
|
||||
info_plist.AddPListKeyValuePair ("NSExtension", "dict",
|
||||
@"
|
||||
<key>NSExtensionMainStoryboard</key>
|
||||
<string>TodayView</string>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.widget-extension</string>
|
||||
");
|
||||
Harness.Save (info_plist, target_info_plist);
|
||||
}
|
||||
|
||||
protected override string Imports {
|
||||
get {
|
||||
return IsFSharp ? "$(MSBuildExtensionsPath)\\Xamarin\\WatchOS\\Xamarin.WatchOS.FSharp.targets" : "$(MSBuildExtensionsPath)\\Xamarin\\WatchOS\\Xamarin.WatchOS.CSharp.targets";
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ExecuteInternal ()
|
||||
{
|
||||
ExtensionName = Name + " Today Extension";
|
||||
AppName = Name + " Today";
|
||||
|
||||
switch (OutputType) {
|
||||
case "Exe":
|
||||
TodayExtensionProjectPath = Path.Combine (TargetDirectory, Path.GetFileNameWithoutExtension (TemplateProjectPath) + "-today-extension." + ProjectFileExtension);
|
||||
TodayContainerProjectPath = Path.Combine (TargetDirectory, Path.GetFileNameWithoutExtension (TemplateProjectPath) + "-today." + ProjectFileExtension);
|
||||
CreateTodayExtensionProject ();
|
||||
CreateTodayContainerProject ();
|
||||
break;
|
||||
case "Library":
|
||||
base.ExecuteInternal ();
|
||||
break;
|
||||
default:
|
||||
throw new Exception (string.Format ("Unknown OutputType: {0}", OutputType));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ namespace xharness
|
|||
void CreateWatchOSAppProject ()
|
||||
{
|
||||
var csproj = new XmlDocument ();
|
||||
var suffix = "-watchos-app";
|
||||
csproj.LoadWithoutNetworkAccess (Path.Combine (Harness.WatchOSAppTemplate, "App.csproj"));
|
||||
csproj.FindAndReplace ("%WATCHAPP_PATH%", Path.GetFullPath (Harness.WatchOSAppTemplate).Replace ('/', '\\') + "\\");
|
||||
csproj.FindAndReplace ("%WATCHEXTENSION_CSPROJ%", Path.GetFileName (WatchOSExtensionProjectPath));
|
||||
|
@ -27,6 +28,7 @@ namespace xharness
|
|||
csproj.SetProjectReferenceValue (Path.GetFileName (WatchOSExtensionProjectPath), "Name", Path.GetFileNameWithoutExtension (WatchOSExtensionProjectPath));
|
||||
WatchOSAppGuid = "{" + Harness.NewStableGuid ().ToString ().ToUpper () + "}";
|
||||
csproj.SetProjectGuid (WatchOSAppGuid);
|
||||
csproj.FixInfoPListInclude (suffix);
|
||||
Harness.Save (csproj, WatchOSAppProjectPath);
|
||||
|
||||
XmlDocument info_plist = new XmlDocument ();
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>xharness</RootNamespace>
|
||||
<AssemblyName>xharness</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -29,6 +29,10 @@
|
|||
<Externalconsole>true</Externalconsole>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(RunConfiguration)' == 'Default' ">
|
||||
<StartAction>Project</StartAction>
|
||||
<StartArguments>--verbose --jenkins:server --autoconf --rootdir ..</StartArguments>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
|
@ -70,6 +74,10 @@
|
|||
<Compile Include="Log.cs" />
|
||||
<Compile Include="GitHub.cs" />
|
||||
<Compile Include="Extensions.cs" />
|
||||
<Compile Include="..\mtouch\Cache.cs">
|
||||
<Link>Cache.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="TodayExtensionTarget.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="..\..\jenkins\nunit-summary.xslt">
|
||||
|
|
Загрузка…
Ссылка в новой задаче