2018-11-16 21:31:40 +03:00
using System ;
2016-05-26 16:06:52 +03:00
using System.Collections.Generic ;
2016-06-17 18:21:18 +03:00
using System.Diagnostics ;
2016-05-26 16:06:52 +03:00
using System.IO ;
using System.Linq ;
2019-03-07 15:14:53 +03:00
using System.Security.Cryptography ;
2016-05-26 16:06:52 +03:00
using System.Text ;
2016-06-17 18:21:18 +03:00
using System.Threading ;
using System.Threading.Tasks ;
2016-05-26 16:06:52 +03:00
using System.Xml ;
2017-06-06 23:32:25 +03:00
using Xamarin.Utils ;
2018-11-16 21:31:40 +03:00
using xharness.BCLTestImporter ;
2016-05-26 16:06:52 +03:00
namespace xharness
{
public enum HarnessAction
{
None ,
Configure ,
Run ,
Install ,
2017-01-02 10:58:46 +03:00
Uninstall ,
2016-06-06 13:48:53 +03:00
Jenkins ,
2016-05-26 16:06:52 +03:00
}
public class Harness
{
public HarnessAction Action { get ; set ; }
public int Verbosity { get ; set ; }
2016-06-17 18:21:18 +03:00
public Log HarnessLog { get ; set ; }
2017-01-16 09:24:14 +03:00
public bool UseSystem { get ; set ; } // if the system XI/XM should be used, or the locally build XI/XM.
2017-08-03 15:31:02 +03:00
public HashSet < string > Labels { get ; } = new HashSet < string > ( ) ;
2016-05-26 16:06:52 +03:00
2018-11-20 20:14:16 +03:00
public string XIBuildPath {
get { return Path . GetFullPath ( Path . Combine ( RootDirectory , ".." , "tools" , "xibuild" , "xibuild" ) ) ; }
}
2017-11-28 16:27:31 +03:00
public static string Timestamp {
get {
return $"{DateTime.Now:yyyyMMdd_HHmmss}" ;
}
}
2016-05-26 16:06:52 +03:00
// This is the maccore/tests directory.
2019-05-28 17:04:42 +03:00
static string root_directory ;
public static string RootDirectory {
2016-05-26 16:06:52 +03:00
get {
2017-01-16 09:24:14 +03:00
if ( root_directory = = null ) {
var testAssemblyDirectory = Path . GetDirectoryName ( System . Reflection . Assembly . GetExecutingAssembly ( ) . Location ) ;
var dir = testAssemblyDirectory ;
var path = Path . Combine ( testAssemblyDirectory , ".git" ) ;
while ( ! Directory . Exists ( path ) & & path . Length > 3 ) {
dir = Path . GetDirectoryName ( dir ) ;
path = Path . Combine ( dir , ".git" ) ;
}
if ( ! Directory . Exists ( path ) )
throw new Exception ( "Could not find the xamarin-macios repo." ) ;
path = Path . Combine ( Path . GetDirectoryName ( path ) , "tests" ) ;
if ( ! Directory . Exists ( path ) )
throw new Exception ( "Could not find the tests directory." ) ;
root_directory = path ;
}
2016-05-26 16:06:52 +03:00
return root_directory ;
}
set {
root_directory = value ;
}
}
2017-09-22 19:04:32 +03:00
public List < iOSTestProject > IOSTestProjects { get ; set ; } = new List < iOSTestProject > ( ) ;
2016-11-30 18:38:32 +03:00
public List < MacTestProject > MacTestProjects { get ; set ; } = new List < MacTestProject > ( ) ;
2017-02-01 19:05:08 +03:00
2016-05-26 16:06:52 +03:00
// Configure
public bool AutoConf { get ; set ; }
2016-06-07 19:49:20 +03:00
public bool Mac { get ; set ; }
2016-05-26 16:06:52 +03:00
public string WatchOSContainerTemplate { get ; set ; }
public string WatchOSAppTemplate { get ; set ; }
public string WatchOSExtensionTemplate { get ; set ; }
2017-01-04 21:45:26 +03:00
public string TodayContainerTemplate { get ; set ; }
public string TodayExtensionTemplate { get ; set ; }
2019-04-05 15:07:39 +03:00
public string BCLTodayExtensionTemplate { get ; set ; }
2016-05-26 16:06:52 +03:00
public string 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.
2017-01-27 12:52:49 +03:00
public bool INCLUDE_IOS { get ; set ; }
public bool INCLUDE_TVOS { get ; set ; }
2016-05-26 16:06:52 +03:00
public bool INCLUDE_WATCH { get ; set ; }
2017-01-27 12:52:49 +03:00
public bool INCLUDE_MAC { get ; set ; }
2016-06-06 13:48:53 +03:00
public string JENKINS_RESULTS_DIRECTORY { get ; set ; } // Use same name as in Makefiles, so that a grep finds it.
2016-06-13 07:20:33 +03:00
public string MAC_DESTDIR { get ; set ; }
public string IOS_DESTDIR { get ; set ; }
2019-04-26 17:44:29 +03:00
public string MONO_IOS_SDK_DESTDIR { get ; set ; }
public string MONO_MAC_SDK_DESTDIR { get ; set ; }
2018-06-13 19:53:57 +03:00
public bool IncludeMac32 { get ; set ; }
2019-01-10 18:43:02 +03:00
public bool ENABLE_XAMARIN { get ; set ; }
2016-05-26 16:06:52 +03:00
// Run
2016-11-16 17:23:11 +03:00
public AppRunnerTarget Target { get ; set ; }
2017-08-23 19:22:53 +03:00
public string SdkRoot { get ; set ; }
2018-08-04 00:06:23 +03:00
public string SdkRoot94 { get ; set ; }
2016-05-26 16:06:52 +03:00
public string Configuration { get ; set ; } = "Debug" ;
public string LogFile { get ; set ; }
2016-06-06 13:48:53 +03:00
public string LogDirectory { get ; set ; } = Environment . CurrentDirectory ;
2019-05-11 13:03:38 +03:00
public double Timeout { get ; set ; } = 15 ; // in minutes
2016-05-26 16:06:52 +03:00
public double LaunchTimeout { get ; set ; } // in minutes
2016-06-06 13:48:53 +03:00
public bool DryRun { get ; set ; } // Most things don't support this. If you need it somewhere, implement it!
public string JenkinsConfiguration { get ; set ; }
2016-08-05 23:28:13 +03:00
public Dictionary < string , string > EnvironmentVariables { get ; set ; } = new Dictionary < string , string > ( ) ;
2017-08-29 15:59:37 +03:00
public string MarkdownSummaryPath { get ; set ; }
2017-11-22 18:03:36 +03:00
public string PeriodicCommand { get ; set ; }
public string PeriodicCommandArguments { get ; set ; }
public TimeSpan PeriodicCommandInterval { get ; set ; }
2017-11-28 21:16:46 +03:00
// whether tests that require access to system resources (system contacts, photo library, etc) should be executed or not
public bool IncludeSystemPermissionTests { get ; set ; } = true ;
2016-05-26 16:06:52 +03:00
public Harness ( )
{
2016-06-18 18:45:56 +03:00
LaunchTimeout = InWrench ? 3 : 120 ;
2016-05-26 16:06:52 +03:00
}
2018-08-04 00:06:23 +03:00
static string FindXcode ( string path )
{
var p = path ;
do {
if ( p = = "/" ) {
throw new Exception ( string . Format ( "Could not find Xcode.app in {0}" , path ) ) ;
} else if ( File . Exists ( Path . Combine ( p , "Contents" , "MacOS" , "Xcode" ) ) ) {
return p ;
}
p = Path . GetDirectoryName ( p ) ;
} while ( true ) ;
}
2016-05-26 16:06:52 +03:00
public string XcodeRoot {
get {
2018-08-04 00:06:23 +03:00
return FindXcode ( SdkRoot ) ;
}
}
public string Xcode94Root {
get {
return FindXcode ( SdkRoot94 ) ;
2016-05-26 16:06:52 +03:00
}
}
2017-06-09 17:24:01 +03:00
Version xcode_version ;
public Version XcodeVersion {
get {
if ( xcode_version = = null ) {
var doc = new XmlDocument ( ) ;
doc . Load ( Path . Combine ( XcodeRoot , "Contents" , "version.plist" ) ) ;
xcode_version = Version . Parse ( doc . SelectSingleNode ( "//key[text() = 'CFBundleShortVersionString']/following-sibling::string" ) . InnerText ) ;
}
return xcode_version ;
}
}
2016-11-24 17:12:51 +03:00
object mlaunch_lock = new object ( ) ;
2016-06-16 02:55:06 +03:00
string DownloadMlaunch ( )
{
2016-08-02 19:14:28 +03:00
// NOTE: the filename part in the url must be unique so that the caching logic works properly.
2018-01-26 06:46:52 +03:00
var mlaunch_url = "https://dl.xamarin.com/ios/mlaunch-acdb43d346c431b2c40663c938c919dcb0e91bd7.zip" ;
2016-11-09 18:14:59 +03:00
var extraction_dir = Path . Combine ( Path . GetTempPath ( ) , Path . GetFileNameWithoutExtension ( mlaunch_url ) ) ;
var mlaunch_path = Path . Combine ( extraction_dir , "bin" , "mlaunch" ) ;
2016-11-24 17:12:51 +03:00
lock ( mlaunch_lock ) {
if ( File . Exists ( mlaunch_path ) )
return mlaunch_path ;
try {
var local_zip = extraction_dir + ".zip" ;
Log ( "Downloading mlaunch to: {0}" , local_zip ) ;
var wc = new System . Net . WebClient ( ) ;
wc . DownloadFile ( mlaunch_url , local_zip ) ;
Log ( "Downloaded mlaunch." ) ;
var tmp_extraction_dir = extraction_dir + ".tmp" ;
if ( Directory . Exists ( tmp_extraction_dir ) )
Directory . Delete ( tmp_extraction_dir , true ) ;
2016-11-25 13:27:08 +03:00
if ( Directory . Exists ( extraction_dir ) )
Directory . Delete ( extraction_dir , true ) ;
2016-11-24 17:12:51 +03:00
Log ( "Extracting mlaunch..." ) ;
using ( var p = new Process ( ) ) {
p . StartInfo . FileName = "unzip" ;
2017-06-06 23:32:25 +03:00
p . StartInfo . Arguments = $"-d {StringUtils.Quote (tmp_extraction_dir)} {StringUtils.Quote (local_zip)}" ;
2016-11-24 17:12:51 +03:00
Log ( "{0} {1}" , p . StartInfo . FileName , p . StartInfo . Arguments ) ;
p . Start ( ) ;
p . WaitForExit ( ) ;
if ( p . ExitCode ! = 0 ) {
Log ( "Could not unzip mlaunch, exit code: {0}" , p . ExitCode ) ;
return mlaunch_path ;
}
2016-11-09 18:14:59 +03:00
}
2016-11-24 17:12:51 +03:00
Directory . Move ( tmp_extraction_dir , extraction_dir ) ;
2016-11-09 18:14:59 +03:00
2016-11-24 17:12:51 +03:00
Log ( "Final mlaunch path: {0}" , mlaunch_path ) ;
} catch ( Exception e ) {
Log ( "Could not download mlaunch: {0}" , e ) ;
}
return mlaunch_path ;
2016-06-16 02:55:06 +03:00
}
}
2016-11-25 14:37:02 +03:00
public string MtouchPath {
get {
return Path . Combine ( IOS_DESTDIR , "Library" , "Frameworks" , "Xamarin.iOS.framework" , "Versions" , "Current" , "bin" , "mtouch" ) ;
}
}
2016-05-26 16:06:52 +03:00
public string MlaunchPath {
get {
2018-04-10 10:53:11 +03:00
return Path . Combine ( IOS_DESTDIR , "Library" , "Frameworks" , "Xamarin.iOS.framework" , "Versions" , "Current" , "bin" , "mlaunch" ) ;
2016-05-26 16:06:52 +03:00
}
}
2016-11-25 14:37:02 +03:00
void LoadConfig ( )
2016-06-10 21:56:48 +03:00
{
ParseConfigFiles ( ) ;
2018-09-03 08:56:44 +03:00
var src_root = Path . GetDirectoryName ( Path . GetFullPath ( RootDirectory ) ) ;
2016-06-10 21:56:48 +03:00
MONO_PATH = Path . GetFullPath ( Path . Combine ( src_root , "external" , "mono" ) ) ;
TVOS_MONO_PATH = MONO_PATH ;
2017-01-27 12:52:49 +03:00
INCLUDE_IOS = make_config . ContainsKey ( "INCLUDE_IOS" ) & & ! string . IsNullOrEmpty ( make_config [ "INCLUDE_IOS" ] ) ;
INCLUDE_TVOS = make_config . ContainsKey ( "INCLUDE_TVOS" ) & & ! string . IsNullOrEmpty ( make_config [ "INCLUDE_TVOS" ] ) ;
2016-06-10 21:56:48 +03:00
JENKINS_RESULTS_DIRECTORY = make_config [ "JENKINS_RESULTS_DIRECTORY" ] ;
2017-01-27 12:52:49 +03:00
INCLUDE_WATCH = make_config . ContainsKey ( "INCLUDE_WATCH" ) & & ! string . IsNullOrEmpty ( make_config [ "INCLUDE_WATCH" ] ) ;
INCLUDE_MAC = make_config . ContainsKey ( "INCLUDE_MAC" ) & & ! string . IsNullOrEmpty ( make_config [ "INCLUDE_MAC" ] ) ;
2016-06-13 07:20:33 +03:00
MAC_DESTDIR = make_config [ "MAC_DESTDIR" ] ;
IOS_DESTDIR = make_config [ "IOS_DESTDIR" ] ;
2017-08-23 19:22:53 +03:00
if ( string . IsNullOrEmpty ( SdkRoot ) )
SdkRoot = make_config [ "XCODE_DEVELOPER_ROOT" ] ;
2018-08-04 00:06:23 +03:00
if ( string . IsNullOrEmpty ( SdkRoot94 ) )
SdkRoot94 = make_config [ "XCODE94_DEVELOPER_ROOT" ] ;
2019-04-26 17:44:29 +03:00
MONO_IOS_SDK_DESTDIR = make_config [ "MONO_IOS_SDK_DESTDIR" ] ;
MONO_MAC_SDK_DESTDIR = make_config [ "MONO_MAC_SDK_DESTDIR" ] ;
2019-01-10 18:43:02 +03:00
ENABLE_XAMARIN = make_config . ContainsKey ( "ENABLE_XAMARIN" ) & & ! string . IsNullOrEmpty ( make_config [ "ENABLE_XAMARIN" ] ) ;
2016-06-10 21:56:48 +03:00
}
2016-05-26 16:06:52 +03:00
void AutoConfigureMac ( )
{
2018-01-16 21:15:59 +03:00
var test_suites = new [ ] {
2018-10-15 17:51:46 +03:00
new { Directory = "apitest" , ProjectFile = "apitest" , Name = "apitest" , GenerateSystem = false } ,
new { Directory = "linker/mac/dont link" , ProjectFile = "dont link-mac" , Name = "dont link" , GenerateSystem = true } ,
2018-01-16 21:15:59 +03:00
} ;
2018-10-15 17:51:46 +03:00
foreach ( var p in test_suites ) {
MacTestProjects . Add ( new MacTestProject ( Path . GetFullPath ( Path . Combine ( RootDirectory , p . Directory + "/" + p . ProjectFile + ".sln" ) ) ) {
Name = p . Name ,
TargetFrameworkFlavor = p . GenerateSystem ? MacFlavors . All : MacFlavors . NonSystem ,
} ) ;
}
2017-02-01 19:05:08 +03:00
2017-10-20 18:14:02 +03:00
MacTestProjects . Add ( new MacTestProject ( Path . GetFullPath ( Path . Combine ( RootDirectory , "introspection" , "Mac" , "introspection-mac.csproj" ) ) , targetFrameworkFlavor : MacFlavors . Modern ) { Name = "introspection" } ) ;
2017-02-01 19:05:08 +03:00
2017-05-08 14:20:01 +03:00
var hard_coded_test_suites = new [ ] {
2018-01-16 21:15:59 +03:00
new { Directory = "mmptest" , ProjectFile = "mmptest" , Name = "mmptest" , IsNUnit = true , Configurations = ( string [ ] ) null , Platform = "x86" , } ,
2018-05-08 08:35:42 +03:00
new { Directory = "msbuild-mac" , ProjectFile = "msbuild-mac" , Name = "MSBuild tests" , IsNUnit = true , Configurations = ( string [ ] ) null , Platform = "x86" } ,
2018-01-16 21:15:59 +03:00
new { Directory = "xammac_tests" , ProjectFile = "xammac_tests" , Name = "xammac tests" , IsNUnit = false , Configurations = new string [ ] { "Debug" , "Release" } , Platform = "AnyCPU" } ,
2018-02-05 17:09:04 +03:00
new { Directory = "linker/mac/link all" , ProjectFile = "link all-mac" , Name = "link all" , IsNUnit = false , Configurations = new string [ ] { "Debug" , "Release" } , Platform = "x86" , } ,
new { Directory = "linker/mac/link sdk" , ProjectFile = "link sdk-mac" , Name = "link sdk" , IsNUnit = false , Configurations = new string [ ] { "Debug" , "Release" } , Platform = "x86" , } ,
2017-05-08 14:20:01 +03:00
} ;
foreach ( var p in hard_coded_test_suites ) {
2018-01-16 21:15:59 +03:00
MacTestProjects . Add ( new MacTestProject ( Path . GetFullPath ( Path . Combine ( RootDirectory , p . Directory + "/" + p . ProjectFile + ".csproj" ) ) , generateVariations : false ) {
2017-05-08 14:20:01 +03:00
Name = p . Name ,
IsNUnitProject = p . IsNUnit ,
SolutionPath = Path . GetFullPath ( Path . Combine ( RootDirectory , "tests-mac.sln" ) ) ,
2017-05-25 08:11:36 +03:00
Configurations = p . Configurations ,
2017-11-22 18:28:32 +03:00
Platform = p . Platform ,
2017-05-08 14:20:01 +03:00
} ) ;
}
2017-02-01 19:05:08 +03:00
[runtime] integrate mono 2017-10 (#2905)
* Update the function name used to initialize libmono-profiler-log, its called mono_profiler_init_log () now.
* [builds] Pass --with-cross-offsets= to crosstv's configure.
* Bump mono to 2017-08.
* Bump mono to 2017-08.
* Force disable 'futimens' and 'utimensat' so that we build with Xcode 9.
This is also needed to build with Xcode 8.3 on High Sierra.
* Remove old AppleTls implementation.
* Bump mono.
* Bump mono to 2017-08.
* Bump mono to 2017-08
* Reenable link-keep-resources-2 test
- This reverts commit 76b759ef22c06cda3ba30aba1ac0d45634e4fbf4.
- 2017-08 has linker fix
* Bump mono to 2017-10
* Revert "Bump mono to 2017-10"
This reverts commit bb7832724e18f8578449e46426382a537f3f4823.
* Bump system mono to 2017-10
* Bump embedded mono to 2017-10
* [runtime] reflect eglib move
https://github.com/mono/mono/commit/9be68f8952ea0e1aad582bfe2f47bad71aee2cc7
* bump mono
* [btouch] remove Security.Tls usage from test
* [mtouch tests] update the function name used to initialize libmono-profiler-log, its called mono_profiler_init_log () now.
see
https://github.com/mono/mono/commit/ea4e4a9ef6fc42570a23026adbe826cf7248290e
fixes:
```
1) Failed : Xamarin.MTouch.Profiling(tvOS)
_mono_profiler_startup_log
Expected: collection containing "_mono_profiler_startup_log"
But was: < "_mono_profiler_init_log" >
at Xamarin.MTouch.Profiling (Xamarin.Profile profile) [0x00106] in <511889694a624cc9a50e0e9b259b05c5>:0
2) Failed : Xamarin.MTouch.Profiling(watchOS)
_mono_profiler_startup_log
Expected: collection containing "_mono_profiler_startup_log"
But was: < "_xamarin_get_block_descriptor", "_mono_profiler_init_log" >
at Xamarin.MTouch.Profiling (Xamarin.Profile profile) [0x00106] in <511889694a624cc9a50e0e9b259b05c5>:0
```
* [mmptest] update log profiler options.
https://github.com/mono/mono/commit/826558a4af624bc0acaea98ec39784e65d278091
deprecated the dash prefix for the mlpd path.
`noallocs` or `nocalls` are not needed, neither of them are default anymore.
* [mmptest] fix link-keep-resources-2 test to cope with more corlib resources.
another corlib resource (mscorlib.xml) was added:
https://github.com/mono/mono/commit/11e95169e787#diff-2d1c64decd91d9a6e8842ab0f0e9438d
* Revert "[mmptest] fix link-keep-resources-2 test to cope with more corlib resources."
This reverts commit 350eb3c174288bbffcc3b7acb15cadb913af25b7.
* [XHarness] Add the Mono.Data.Tds tests.
* Address comments from rolf in the review.
* [mmp regresssion tests] bump mono linker, so mscorlib.xml gets stripped
the test was failing in that way:
> Executing link-keep-resources-2...
> [FAIL] i18n 4/2 data files present: charinfo.nlp, collation.core.bin, collation.tailoring.bin, mscorlib.xml
also update the output, because it's actually expected at least three
elements.
fixes: https://bugzilla.xamarin.com/show_bug.cgi?id=59277
* bump mono
fixes crash in tvOS: https://github.com/mono/mono/pull/5812
* bump mono for updated BCL tests
see https://github.com/mono/mono/pull/5820
* [mono] set 2017-10 branch in .gitmodules
* [macos] Fix guiunit error on clean builds by depending on correct copy (#2912)
* [macos] Fix guiunit error on clean builds by depending on correct copy
- From a clean build making a BCL test would error due to the non-mobile guiunit not being built
- This was because the Makefile-mac.inc target was incorrect
- This was because xharness assumed that non variation based targets were always Modern
- However, BCL tests are Full, not Modern
* Code review change
* Swap to var to reduce diff
* Revert changes in the paths for GuiUnit.
* [XHarness] Add the System.IO.Compression bcl tests. (#2918)
* [XHarness] Add the System.IO.Compression bcl tests.
* [XHarness] Add bcl tests for System.IO.Compression.FileSystem. (#2924)
* [XHarness] Add the System.IO.Compression bcl tests.
* Ensure that resources are correctly copied in the bundles.
* [XHarness] Add bcl tests for System.IO.Compression.FileSystem.
* As per review, make the Mac test app name match the tests that are ran.
* [XHarness] Add Mono.CSharp tests on ios. (#2927)
* [XHarness] Add Mono.CSharp tests on ios.
* Bump mono to bring changes in the mono.csharp tests.
* [xtro-sharpie] fix TypeDefinition access due to Cecil change
* Bump mono
* bump mono
fixes
- https://bugzilla.xamarin.com/show_bug.cgi?id=60480
- https://bugzilla.xamarin.com/show_bug.cgi?id=60482
* bump mono
more fixes around conflicting paths when tests are run in parallel.
* Bump for mono/mono@2017-10
2017-11-14 23:30:08 +03:00
var bcl_suites = new string [ ] {
"mscorlib" ,
} ;
2017-02-01 19:05:08 +03:00
foreach ( var p in bcl_suites ) {
2017-10-28 00:44:22 +03:00
foreach ( var flavor in new MacFlavors [ ] { MacFlavors . Full , MacFlavors . Modern } ) {
var bclTestInfo = new MacBCLTestInfo ( this , p , flavor ) ;
var bclTestProject = new MacTestProject ( bclTestInfo . ProjectPath , targetFrameworkFlavor : flavor , generateVariations : false ) {
Name = p ,
2017-11-22 18:28:32 +03:00
BCLInfo = bclTestInfo ,
Platform = "AnyCPU" ,
2017-10-28 00:44:22 +03:00
} ;
MacTestProjects . Add ( bclTestProject ) ;
}
2017-02-01 19:05:08 +03:00
}
2018-11-14 21:26:30 +03:00
foreach ( var flavor in new MonoNativeFlavor [ ] { MonoNativeFlavor . Compat , MonoNativeFlavor . Unified } ) {
foreach ( var macFlavor in new MacFlavors [ ] { MacFlavors . Full , MacFlavors . Modern } ) {
var monoNativeInfo = new MacMonoNativeInfo ( this , flavor , macFlavor ) ;
var macTestProject = new MacTestProject ( monoNativeInfo . ProjectPath , targetFrameworkFlavor : macFlavor , generateVariations : true ) {
MonoNativeInfo = monoNativeInfo ,
Name = monoNativeInfo . ProjectName ,
Platform = "AnyCPU"
} ;
MacTestProjects . Add ( macTestProject ) ;
}
}
2018-12-17 17:28:08 +03:00
2018-12-12 12:38:48 +03:00
var monoImportTestFactory = new BCLTestImportTargetFactory ( this ) ;
2019-01-31 20:28:38 +03:00
MacTestProjects . AddRange ( monoImportTestFactory . GetMacBclTargets ( ) ) ;
2016-05-26 16:06:52 +03:00
}
2016-06-10 21:56:48 +03:00
void AutoConfigureIOS ( )
2016-05-26 16:06:52 +03:00
{
2017-01-26 15:38:39 +03:00
var test_suites = new string [ ] { "monotouch-test" , "framework-test" , "mini" , "interdependent-binding-projects" } ;
var library_projects = new string [ ] { "BundledResources" , "EmbeddedResources" , "bindings-test" , "bindings-test2" , "bindings-framework-test" } ;
2016-05-26 16:06:52 +03:00
var fsharp_test_suites = new string [ ] { "fsharp" } ;
var fsharp_library_projects = new string [ ] { "fsharplibrary" } ;
[runtime] integrate mono 2017-10 (#2905)
* Update the function name used to initialize libmono-profiler-log, its called mono_profiler_init_log () now.
* [builds] Pass --with-cross-offsets= to crosstv's configure.
* Bump mono to 2017-08.
* Bump mono to 2017-08.
* Force disable 'futimens' and 'utimensat' so that we build with Xcode 9.
This is also needed to build with Xcode 8.3 on High Sierra.
* Remove old AppleTls implementation.
* Bump mono.
* Bump mono to 2017-08.
* Bump mono to 2017-08
* Reenable link-keep-resources-2 test
- This reverts commit 76b759ef22c06cda3ba30aba1ac0d45634e4fbf4.
- 2017-08 has linker fix
* Bump mono to 2017-10
* Revert "Bump mono to 2017-10"
This reverts commit bb7832724e18f8578449e46426382a537f3f4823.
* Bump system mono to 2017-10
* Bump embedded mono to 2017-10
* [runtime] reflect eglib move
https://github.com/mono/mono/commit/9be68f8952ea0e1aad582bfe2f47bad71aee2cc7
* bump mono
* [btouch] remove Security.Tls usage from test
* [mtouch tests] update the function name used to initialize libmono-profiler-log, its called mono_profiler_init_log () now.
see
https://github.com/mono/mono/commit/ea4e4a9ef6fc42570a23026adbe826cf7248290e
fixes:
```
1) Failed : Xamarin.MTouch.Profiling(tvOS)
_mono_profiler_startup_log
Expected: collection containing "_mono_profiler_startup_log"
But was: < "_mono_profiler_init_log" >
at Xamarin.MTouch.Profiling (Xamarin.Profile profile) [0x00106] in <511889694a624cc9a50e0e9b259b05c5>:0
2) Failed : Xamarin.MTouch.Profiling(watchOS)
_mono_profiler_startup_log
Expected: collection containing "_mono_profiler_startup_log"
But was: < "_xamarin_get_block_descriptor", "_mono_profiler_init_log" >
at Xamarin.MTouch.Profiling (Xamarin.Profile profile) [0x00106] in <511889694a624cc9a50e0e9b259b05c5>:0
```
* [mmptest] update log profiler options.
https://github.com/mono/mono/commit/826558a4af624bc0acaea98ec39784e65d278091
deprecated the dash prefix for the mlpd path.
`noallocs` or `nocalls` are not needed, neither of them are default anymore.
* [mmptest] fix link-keep-resources-2 test to cope with more corlib resources.
another corlib resource (mscorlib.xml) was added:
https://github.com/mono/mono/commit/11e95169e787#diff-2d1c64decd91d9a6e8842ab0f0e9438d
* Revert "[mmptest] fix link-keep-resources-2 test to cope with more corlib resources."
This reverts commit 350eb3c174288bbffcc3b7acb15cadb913af25b7.
* [XHarness] Add the Mono.Data.Tds tests.
* Address comments from rolf in the review.
* [mmp regresssion tests] bump mono linker, so mscorlib.xml gets stripped
the test was failing in that way:
> Executing link-keep-resources-2...
> [FAIL] i18n 4/2 data files present: charinfo.nlp, collation.core.bin, collation.tailoring.bin, mscorlib.xml
also update the output, because it's actually expected at least three
elements.
fixes: https://bugzilla.xamarin.com/show_bug.cgi?id=59277
* bump mono
fixes crash in tvOS: https://github.com/mono/mono/pull/5812
* bump mono for updated BCL tests
see https://github.com/mono/mono/pull/5820
* [mono] set 2017-10 branch in .gitmodules
* [macos] Fix guiunit error on clean builds by depending on correct copy (#2912)
* [macos] Fix guiunit error on clean builds by depending on correct copy
- From a clean build making a BCL test would error due to the non-mobile guiunit not being built
- This was because the Makefile-mac.inc target was incorrect
- This was because xharness assumed that non variation based targets were always Modern
- However, BCL tests are Full, not Modern
* Code review change
* Swap to var to reduce diff
* Revert changes in the paths for GuiUnit.
* [XHarness] Add the System.IO.Compression bcl tests. (#2918)
* [XHarness] Add the System.IO.Compression bcl tests.
* [XHarness] Add bcl tests for System.IO.Compression.FileSystem. (#2924)
* [XHarness] Add the System.IO.Compression bcl tests.
* Ensure that resources are correctly copied in the bundles.
* [XHarness] Add bcl tests for System.IO.Compression.FileSystem.
* As per review, make the Mac test app name match the tests that are ran.
* [XHarness] Add Mono.CSharp tests on ios. (#2927)
* [XHarness] Add Mono.CSharp tests on ios.
* Bump mono to bring changes in the mono.csharp tests.
* [xtro-sharpie] fix TypeDefinition access due to Cecil change
* Bump mono
* bump mono
fixes
- https://bugzilla.xamarin.com/show_bug.cgi?id=60480
- https://bugzilla.xamarin.com/show_bug.cgi?id=60482
* bump mono
more fixes around conflicting paths when tests are run in parallel.
* Bump for mono/mono@2017-10
2017-11-14 23:30:08 +03:00
var bcl_suites = new string [ ] {
"mscorlib" ,
} ;
2017-09-22 19:04:32 +03:00
var bcl_skip_watchos = new string [ ] {
} ;
IOSTestProjects . Add ( new iOSTestProject ( Path . GetFullPath ( Path . Combine ( RootDirectory , "bcl-test/mscorlib/mscorlib-0.csproj" ) ) , false ) ) ;
IOSTestProjects . Add ( new iOSTestProject ( Path . GetFullPath ( Path . Combine ( RootDirectory , "bcl-test/mscorlib/mscorlib-1.csproj" ) ) , false ) ) ;
2016-05-26 16:06:52 +03:00
foreach ( var p in test_suites )
2018-10-03 16:33:30 +03:00
IOSTestProjects . Add ( new iOSTestProject ( Path . GetFullPath ( Path . Combine ( RootDirectory , p + "/" + p + ".csproj" ) ) ) { Name = p } ) ;
2016-05-26 16:06:52 +03:00
foreach ( var p in fsharp_test_suites )
2018-10-03 16:33:30 +03:00
IOSTestProjects . Add ( new iOSTestProject ( Path . GetFullPath ( Path . Combine ( RootDirectory , p + "/" + p + ".fsproj" ) ) ) { Name = p } ) ;
2016-05-26 16:06:52 +03:00
foreach ( var p in library_projects )
2018-10-03 16:33:30 +03:00
IOSTestProjects . Add ( new iOSTestProject ( Path . GetFullPath ( Path . Combine ( RootDirectory , p + "/" + p + ".csproj" ) ) , false ) { Name = p } ) ;
2016-05-26 16:06:52 +03:00
foreach ( var p in fsharp_library_projects )
2018-10-03 16:33:30 +03:00
IOSTestProjects . Add ( new iOSTestProject ( Path . GetFullPath ( Path . Combine ( RootDirectory , p + "/" + p + ".fsproj" ) ) , false ) { Name = p } ) ;
2017-02-01 19:05:08 +03:00
foreach ( var p in bcl_suites ) {
2017-10-28 00:44:22 +03:00
BCLTestInfo bclTestInfo = new BCLTestInfo ( this , p ) ;
2017-09-22 19:04:32 +03:00
IOSTestProjects . Add ( new iOSTestProject ( Path . GetFullPath ( Path . Combine ( RootDirectory , "bcl-test/" + p + "/" + p + ".csproj" ) ) ) {
SkipwatchOSVariation = bcl_skip_watchos . Contains ( p ) ,
2018-10-03 16:33:30 +03:00
BCLInfo = bclTestInfo ,
Name = p
2017-09-22 19:04:32 +03:00
} ) ;
2017-02-01 19:05:08 +03:00
}
2017-09-22 19:04:32 +03:00
IOSTestProjects . Add ( new iOSTestProject ( Path . GetFullPath ( Path . Combine ( RootDirectory , "introspection" , "iOS" , "introspection-ios.csproj" ) ) ) { Name = "introspection" } ) ;
2018-02-05 17:09:04 +03:00
IOSTestProjects . Add ( new iOSTestProject ( Path . GetFullPath ( Path . Combine ( RootDirectory , "linker" , "ios" , "dont link" , "dont link.csproj" ) ) ) { Configurations = new string [ ] { "Debug" , "Release" } } ) ;
IOSTestProjects . Add ( new iOSTestProject ( Path . GetFullPath ( Path . Combine ( RootDirectory , "linker" , "ios" , "link all" , "link all.csproj" ) ) ) { Configurations = new string [ ] { "Debug" , "Release" } } ) ;
IOSTestProjects . Add ( new iOSTestProject ( Path . GetFullPath ( Path . Combine ( RootDirectory , "linker" , "ios" , "link sdk" , "link sdk.csproj" ) ) ) { Configurations = new string [ ] { "Debug" , "Release" } } ) ;
2016-06-06 13:48:53 +03:00
2018-11-14 21:26:30 +03:00
foreach ( var flavor in new MonoNativeFlavor [ ] { MonoNativeFlavor . Compat , MonoNativeFlavor . Unified } ) {
var monoNativeInfo = new MonoNativeInfo ( this , flavor ) ;
var iosTestProject = new iOSTestProject ( monoNativeInfo . ProjectPath , generateVariations : false ) {
MonoNativeInfo = monoNativeInfo ,
2019-05-10 10:29:23 +03:00
Name = monoNativeInfo . ProjectName ,
SkipwatchOSARM64_32Variation = monoNativeInfo . ProjectName . Contains ( "compat" ) ,
2018-11-14 21:26:30 +03:00
} ;
IOSTestProjects . Add ( iosTestProject ) ;
}
2018-11-16 21:31:40 +03:00
// add all the tests that are using the precompiled mono assemblies
var monoImportTestFactory = new BCLTestImportTargetFactory ( this ) ;
2019-01-31 20:28:38 +03:00
IOSTestProjects . AddRange ( monoImportTestFactory . GetiOSBclTargets ( ) ) ;
2018-11-16 21:31:40 +03:00
2016-11-25 19:36:04 +03:00
WatchOSContainerTemplate = Path . GetFullPath ( Path . Combine ( RootDirectory , "templates/WatchContainer" ) ) ;
WatchOSAppTemplate = Path . GetFullPath ( Path . Combine ( RootDirectory , "templates/WatchApp" ) ) ;
WatchOSExtensionTemplate = Path . GetFullPath ( Path . Combine ( RootDirectory , "templates/WatchExtension" ) ) ;
2017-01-04 21:45:26 +03:00
TodayContainerTemplate = Path . GetFullPath ( Path . Combine ( RootDirectory , "templates" , "TodayContainer" ) ) ;
TodayExtensionTemplate = Path . GetFullPath ( Path . Combine ( RootDirectory , "templates" , "TodayExtension" ) ) ;
2019-04-05 15:07:39 +03:00
BCLTodayExtensionTemplate = Path . GetFullPath ( Path . Combine ( RootDirectory , "bcl-test" , "BCLTests" , "templates" , "today" ) ) ;
2016-05-26 16:06:52 +03:00
}
2017-01-05 01:05:04 +03:00
Dictionary < string , string > make_config = new Dictionary < string , string > ( ) ;
IEnumerable < string > FindConfigFiles ( string name )
2016-05-26 16:06:52 +03:00
{
2017-01-05 01:05:04 +03:00
var dir = Path . GetFullPath ( RootDirectory ) ;
2016-05-26 16:06:52 +03:00
while ( dir ! = "/" ) {
var file = Path . Combine ( dir , name ) ;
if ( File . Exists ( file ) )
yield return file ;
dir = Path . GetDirectoryName ( dir ) ;
}
}
2017-01-05 01:05:04 +03:00
void ParseConfigFiles ( )
2016-05-26 16:06:52 +03:00
{
2017-01-16 09:24:14 +03:00
ParseConfigFiles ( FindConfigFiles ( UseSystem ? "test-system.config" : "test.config" ) ) ;
2016-05-26 16:06:52 +03:00
ParseConfigFiles ( FindConfigFiles ( "Make.config.local" ) ) ;
ParseConfigFiles ( FindConfigFiles ( "Make.config" ) ) ;
}
2017-01-05 01:05:04 +03:00
void ParseConfigFiles ( IEnumerable < string > files )
2016-05-26 16:06:52 +03:00
{
foreach ( var file in files )
ParseConfigFile ( file ) ;
}
2017-01-05 01:05:04 +03:00
void ParseConfigFile ( string file )
2016-05-26 16:06:52 +03:00
{
if ( string . IsNullOrEmpty ( file ) )
return ;
foreach ( var line in File . ReadAllLines ( file ) ) {
var eq = line . IndexOf ( '=' ) ;
if ( eq = = - 1 )
continue ;
var key = line . Substring ( 0 , eq ) ;
if ( ! make_config . ContainsKey ( key ) )
make_config [ key ] = line . Substring ( eq + 1 ) ;
}
}
public int Configure ( )
{
2019-02-05 14:55:46 +03:00
return Mac ? ConfigureMac ( ) : ConfigureIOS ( ) ;
2016-05-26 16:06:52 +03:00
}
2019-02-05 14:55:46 +03:00
int ConfigureMac ( )
2016-05-26 16:06:52 +03:00
{
2019-02-05 14:55:46 +03:00
int rv = 0 ;
2016-05-26 16:06:52 +03:00
var classic_targets = new List < MacClassicTarget > ( ) ;
var unified_targets = new List < MacUnifiedTarget > ( ) ;
var hardcoded_unified_targets = new List < MacUnifiedTarget > ( ) ;
2017-10-28 00:44:22 +03:00
Action < MacTarget , string , bool > configureTarget = ( MacTarget target , string file , bool isNUnitProject ) = > {
target . TemplateProjectPath = file ;
target . Harness = this ;
target . IsNUnitProject = isNUnitProject ;
target . Execute ( ) ;
} ;
2016-05-26 16:06:52 +03:00
RootDirectory = Path . GetFullPath ( RootDirectory ) . TrimEnd ( '/' ) ;
if ( AutoConf )
AutoConfigureMac ( ) ;
2017-02-01 19:05:08 +03:00
2017-10-28 00:44:22 +03:00
foreach ( var bclTestInfo in MacTestProjects . Where ( x = > x . BCLInfo ! = null ) . Select ( x = > x . BCLInfo ) )
bclTestInfo . Convert ( ) ;
2018-11-14 21:26:30 +03:00
foreach ( var monoNativeInfo in MacTestProjects . Where ( x = > x . MonoNativeInfo ! = null ) . Select ( x = > x . MonoNativeInfo ) )
monoNativeInfo . Convert ( ) ;
2016-06-10 21:56:48 +03:00
foreach ( var proj in MacTestProjects . Where ( ( v ) = > v . GenerateVariations ) ) {
2017-03-30 19:01:15 +03:00
var file = Path . ChangeExtension ( proj . Path , "csproj" ) ;
2019-02-05 23:38:47 +03:00
2018-11-14 21:26:30 +03:00
if ( proj . MonoNativeInfo ! = null )
file = proj . MonoNativeInfo . TemplatePath ;
2019-02-05 23:38:47 +03:00
2019-02-05 14:55:46 +03:00
if ( ! File . Exists ( file ) ) {
Console . WriteLine ( $"Can't find the project file {file}." ) ;
rv = 1 ;
continue ;
}
2016-11-30 18:38:32 +03:00
foreach ( bool thirtyTwoBit in new bool [ ] { false , true } )
{
2017-10-20 18:14:02 +03:00
if ( proj . GenerateModern ) {
2017-10-28 00:44:22 +03:00
var modern = new MacUnifiedTarget ( true , thirtyTwoBit ) ;
2018-11-14 21:26:30 +03:00
modern . MonoNativeInfo = proj . MonoNativeInfo ;
2017-10-28 00:44:22 +03:00
configureTarget ( modern , file , proj . IsNUnitProject ) ;
unified_targets . Add ( modern ) ;
2017-10-20 18:14:02 +03:00
}
2016-11-30 18:38:32 +03:00
2017-10-20 18:14:02 +03:00
if ( proj . GenerateFull ) {
2017-10-28 00:44:22 +03:00
var full = new MacUnifiedTarget ( false , thirtyTwoBit ) ;
2018-11-14 21:26:30 +03:00
full . MonoNativeInfo = proj . MonoNativeInfo ;
2017-10-28 00:44:22 +03:00
configureTarget ( full , file , proj . IsNUnitProject ) ;
unified_targets . Add ( full ) ;
2016-11-30 18:38:32 +03:00
}
}
2017-10-28 00:44:22 +03:00
2018-10-15 17:51:46 +03:00
if ( proj . GenerateSystem ) {
var system = new MacUnifiedTarget ( false , false ) ;
system . System = true ;
configureTarget ( system , file , proj . IsNUnitProject ) ;
unified_targets . Add ( system ) ;
}
2018-11-14 21:26:30 +03:00
if ( proj . MonoNativeInfo = = null ) {
var classic = new MacClassicTarget ( ) ;
configureTarget ( classic , file , false ) ;
classic_targets . Add ( classic ) ;
}
2016-05-26 16:06:52 +03:00
}
2017-10-28 00:44:22 +03:00
foreach ( var proj in MacTestProjects . Where ( v = > ! v . GenerateVariations ) ) {
2016-06-10 21:56:48 +03:00
var file = proj . Path ;
2017-10-28 00:44:22 +03:00
var unified = new MacUnifiedTarget ( proj . GenerateModern , thirtyTwoBit : false , shouldSkipProjectGeneration : true ) ;
unified . BCLInfo = proj . BCLInfo ;
configureTarget ( unified , file , proj . IsNUnitProject ) ;
hardcoded_unified_targets . Add ( unified ) ;
2016-05-26 16:06:52 +03:00
}
2017-10-28 00:44:22 +03:00
MakefileGenerator . CreateMacMakefile ( this , classic_targets . Union < MacTarget > ( unified_targets ) . Union ( hardcoded_unified_targets ) ) ;
2019-02-05 14:55:46 +03:00
return rv ;
2016-05-26 16:06:52 +03:00
}
2019-02-05 14:55:46 +03:00
int ConfigureIOS ( )
2016-05-26 16:06:52 +03:00
{
2019-02-05 14:55:46 +03:00
var rv = 0 ;
2016-05-26 16:06:52 +03:00
var unified_targets = new List < UnifiedTarget > ( ) ;
var tvos_targets = new List < TVOSTarget > ( ) ;
var watchos_targets = new List < WatchOSTarget > ( ) ;
2017-01-04 21:45:26 +03:00
var today_targets = new List < TodayExtensionTarget > ( ) ;
2016-05-26 16:06:52 +03:00
RootDirectory = Path . GetFullPath ( RootDirectory ) . TrimEnd ( '/' ) ;
if ( AutoConf )
2016-06-10 21:56:48 +03:00
AutoConfigureIOS ( ) ;
2016-05-26 16:06:52 +03:00
2017-10-28 00:44:22 +03:00
foreach ( var bclTestInfo in IOSTestProjects . Where ( x = > x . BCLInfo ! = null ) . Select ( x = > x . BCLInfo ) )
bclTestInfo . Convert ( ) ;
2018-11-14 21:26:30 +03:00
foreach ( var monoNativeInfo in IOSTestProjects . Where ( x = > x . MonoNativeInfo ! = null ) . Select ( x = > x . MonoNativeInfo ) )
monoNativeInfo . Convert ( ) ;
2016-05-26 16:06:52 +03:00
2016-06-10 21:56:48 +03:00
foreach ( var proj in IOSTestProjects ) {
2016-06-06 13:48:53 +03:00
var file = proj . Path ;
2019-02-05 23:38:47 +03:00
2018-11-14 21:26:30 +03:00
if ( proj . MonoNativeInfo ! = null )
file = proj . MonoNativeInfo . TemplatePath ;
2019-02-05 23:38:47 +03:00
2019-02-05 14:55:46 +03:00
if ( ! File . Exists ( file ) ) {
Console . WriteLine ( $"Can't find the project file {file}." ) ;
rv = 1 ;
continue ;
}
2016-05-26 16:06:52 +03:00
2017-09-22 19:04:32 +03:00
if ( ! proj . SkipwatchOSVariation ) {
var watchos = new WatchOSTarget ( ) {
TemplateProjectPath = file ,
Harness = this ,
TestProject = proj ,
} ;
watchos . Execute ( ) ;
watchos_targets . Add ( watchos ) ;
}
if ( ! proj . SkiptvOSVariation ) {
var tvos = new TVOSTarget ( ) {
TemplateProjectPath = file ,
Harness = this ,
TestProject = proj ,
} ;
tvos . Execute ( ) ;
tvos_targets . Add ( tvos ) ;
}
if ( ! proj . SkipiOSVariation ) {
var unified = new UnifiedTarget ( ) {
TemplateProjectPath = file ,
Harness = this ,
TestProject = proj ,
} ;
unified . Execute ( ) ;
unified_targets . Add ( unified ) ;
var today = new TodayExtensionTarget {
TemplateProjectPath = file ,
Harness = this ,
TestProject = proj ,
} ;
today . Execute ( ) ;
today_targets . Add ( today ) ;
}
2016-05-26 16:06:52 +03:00
}
SolutionGenerator . CreateSolution ( this , watchos_targets , "watchos" ) ;
SolutionGenerator . CreateSolution ( this , tvos_targets , "tvos" ) ;
2017-01-04 21:45:26 +03:00
SolutionGenerator . CreateSolution ( this , today_targets , "today" ) ;
MakefileGenerator . CreateMakefile ( this , unified_targets , tvos_targets , watchos_targets , today_targets ) ;
2019-02-05 14:55:46 +03:00
return rv ;
2016-05-26 16:06:52 +03:00
}
public int Install ( )
{
2016-06-17 18:21:18 +03:00
if ( HarnessLog = = null )
HarnessLog = new ConsoleLog ( ) ;
2016-06-10 21:56:48 +03:00
foreach ( var project in IOSTestProjects ) {
2016-05-26 16:06:52 +03:00
var runner = new AppRunner ( ) {
Harness = this ,
2016-06-06 13:48:53 +03:00
ProjectFile = project . Path ,
2016-06-17 18:21:18 +03:00
MainLog = HarnessLog ,
2016-05-26 16:06:52 +03:00
} ;
2019-02-20 08:33:30 +03:00
using ( var install_log = new AppInstallMonitorLog ( runner . MainLog ) ) {
var rv = runner . InstallAsync ( install_log . CancellationToken ) . Result ;
if ( ! rv . Succeeded )
return rv . ExitCode ;
}
2016-05-26 16:06:52 +03:00
}
return 0 ;
}
2017-01-02 10:58:46 +03:00
public int Uninstall ( )
{
if ( HarnessLog = = null )
HarnessLog = new ConsoleLog ( ) ;
foreach ( var project in IOSTestProjects ) {
var runner = new AppRunner ( )
{
Harness = this ,
ProjectFile = project . Path ,
MainLog = HarnessLog ,
} ;
2017-01-04 21:45:26 +03:00
var rv = runner . UninstallAsync ( ) . Result ;
if ( ! rv . Succeeded )
return rv . ExitCode ;
2017-01-02 10:58:46 +03:00
}
return 0 ;
}
2016-05-26 16:06:52 +03:00
public int Run ( )
{
2016-06-17 18:21:18 +03:00
if ( HarnessLog = = null )
HarnessLog = new ConsoleLog ( ) ;
2016-06-10 21:56:48 +03:00
foreach ( var project in IOSTestProjects ) {
2016-05-26 16:06:52 +03:00
var runner = new AppRunner ( ) {
Harness = this ,
2016-06-06 13:48:53 +03:00
ProjectFile = project . Path ,
2016-06-17 18:21:18 +03:00
MainLog = HarnessLog ,
2016-05-26 16:06:52 +03:00
} ;
2016-06-17 18:21:18 +03:00
var rv = runner . RunAsync ( ) . Result ;
2016-05-26 16:06:52 +03:00
if ( rv ! = 0 )
return rv ;
}
return 0 ;
}
public void Log ( int min_level , string message )
{
if ( Verbosity < min_level )
return ;
Console . WriteLine ( message ) ;
2016-06-06 13:48:53 +03:00
HarnessLog ? . WriteLine ( message ) ;
2016-05-26 16:06:52 +03:00
}
public void Log ( int min_level , string message , params object [ ] args )
{
if ( Verbosity < min_level )
return ;
Console . WriteLine ( message , args ) ;
2016-06-06 13:48:53 +03:00
HarnessLog ? . WriteLine ( message , args ) ;
2016-05-26 16:06:52 +03:00
}
public void Log ( string message )
{
Log ( 0 , message ) ;
}
public void Log ( string message , params object [ ] args )
{
Log ( 0 , message , args ) ;
}
public void LogWrench ( string message , params object [ ] args )
{
2017-11-22 18:03:36 +03:00
// Disable this for now, since we're not uploading directly to wrench anymore, but instead using the Html Report.
//if (!InWrench)
// return;
2016-05-26 16:06:52 +03:00
2017-11-22 18:03:36 +03:00
//Console.WriteLine (message, args);
2016-05-26 16:06:52 +03:00
}
public void LogWrench ( string message )
{
if ( ! InWrench )
return ;
Console . WriteLine ( message ) ;
}
public bool InWrench {
get {
2016-11-15 21:04:37 +03:00
var buildRev = Environment . GetEnvironmentVariable ( "BUILD_REVISION" ) ;
return ! string . IsNullOrEmpty ( buildRev ) & & buildRev ! = "jenkins" ;
}
}
public bool InJenkins {
get {
var buildRev = Environment . GetEnvironmentVariable ( "BUILD_REVISION" ) ;
return ! string . IsNullOrEmpty ( buildRev ) & & buildRev = = "jenkins" ;
2016-05-26 16:06:52 +03:00
}
}
2019-03-20 14:10:18 +03:00
public bool UseGroupedApps {
get {
var groupApps = Environment . GetEnvironmentVariable ( "BCL_GROUPED_APPS" ) ;
return string . IsNullOrEmpty ( groupApps ) | | groupApps = = "grouped" ;
}
}
2016-05-26 16:06:52 +03:00
public int Execute ( )
{
2016-11-25 14:37:02 +03:00
LoadConfig ( ) ;
2016-05-26 16:06:52 +03:00
switch ( Action ) {
case HarnessAction . Configure :
return Configure ( ) ;
case HarnessAction . Run :
return Run ( ) ;
case HarnessAction . Install :
return Install ( ) ;
2017-01-02 10:58:46 +03:00
case HarnessAction . Uninstall :
return Uninstall ( ) ;
2016-06-06 13:48:53 +03:00
case HarnessAction . Jenkins :
return Jenkins ( ) ;
2016-05-26 16:06:52 +03:00
default :
throw new NotImplementedException ( Action . ToString ( ) ) ;
}
}
2016-06-06 13:48:53 +03:00
public int Jenkins ( )
{
2016-06-10 21:56:48 +03:00
if ( AutoConf ) {
AutoConfigureIOS ( ) ;
AutoConfigureMac ( ) ;
}
2016-06-06 13:48:53 +03:00
var jenkins = new Jenkins ( )
{
Harness = this ,
} ;
return jenkins . Run ( ) ;
}
2016-05-26 16:06:52 +03:00
public void Save ( XmlDocument doc , string path )
{
if ( ! File . Exists ( path ) ) {
doc . Save ( path ) ;
Log ( 1 , "Created {0}" , path ) ;
} else {
var tmpPath = path + ".tmp" ;
doc . Save ( tmpPath ) ;
var existing = File . ReadAllText ( path ) ;
var updated = File . ReadAllText ( tmpPath ) ;
if ( existing = = updated ) {
File . Delete ( tmpPath ) ;
Log ( 1 , "Not saved {0}, no change" , path ) ;
} else {
File . Delete ( path ) ;
File . Move ( tmpPath , path ) ;
Log ( 1 , "Updated {0}" , path ) ;
}
}
}
public void Save ( StringWriter doc , string path )
{
if ( ! File . Exists ( path ) ) {
File . WriteAllText ( path , doc . ToString ( ) ) ;
Log ( 1 , "Created {0}" , path ) ;
} else {
var existing = File . ReadAllText ( path ) ;
var updated = doc . ToString ( ) ;
if ( existing = = updated ) {
Log ( 1 , "Not saved {0}, no change" , path ) ;
} else {
File . WriteAllText ( path , updated ) ;
Log ( 1 , "Updated {0}" , path ) ;
}
}
}
public void Save ( string doc , string path )
{
if ( ! File . Exists ( path ) ) {
File . WriteAllText ( path , doc ) ;
Log ( 1 , "Created {0}" , path ) ;
} else {
var existing = File . ReadAllText ( path ) ;
if ( existing = = doc ) {
Log ( 1 , "Not saved {0}, no change" , path ) ;
} else {
File . WriteAllText ( path , doc ) ;
Log ( 1 , "Updated {0}" , path ) ;
}
}
}
// We want guids that nobody else has, but we also want to generate the same guid
// on subsequent invocations (so that csprojs don't change unnecessarily, which is
// annoying when XS reloads the projects, and also causes unnecessary rebuilds).
// Nothing really breaks when the sequence isn't identical from run to run, so
// this is just a best minimal effort.
static Random guid_generator = new Random ( unchecked ( ( int ) 0xdeadf00d ) ) ;
2019-03-07 15:14:53 +03:00
public Guid NewStableGuid ( string seed = null )
2016-05-26 16:06:52 +03:00
{
var bytes = new byte [ 16 ] ;
2019-03-07 15:14:53 +03:00
if ( seed = = null ) {
guid_generator . NextBytes ( bytes ) ;
} else {
using ( var provider = MD5 . Create ( ) ) {
var inputBytes = Encoding . UTF8 . GetBytes ( seed ) ;
bytes = provider . ComputeHash ( inputBytes ) ;
}
}
2016-05-26 16:06:52 +03:00
return new Guid ( bytes ) ;
}
bool? disable_watchos_on_wrench ;
public bool DisableWatchOSOnWrench {
get {
if ( ! disable_watchos_on_wrench . HasValue )
disable_watchos_on_wrench = ! string . IsNullOrEmpty ( Environment . GetEnvironmentVariable ( "DISABLE_WATCH_ON_WRENCH" ) ) ;
return disable_watchos_on_wrench . Value ;
}
}
2016-06-17 18:21:18 +03:00
public Task < ProcessExecutionResult > ExecuteXcodeCommandAsync ( string executable , string args , Log log , TimeSpan timeout )
{
2016-12-16 14:24:08 +03:00
return ProcessHelper . ExecuteCommandAsync ( Path . Combine ( XcodeRoot , "Contents" , "Developer" , "usr" , "bin" , executable ) , args , log , timeout : timeout ) ;
2016-06-17 18:21:18 +03:00
}
2017-11-28 16:27:31 +03:00
public async Task ShowSimulatorList ( Log log )
2016-06-17 18:21:18 +03:00
{
2016-12-16 14:24:08 +03:00
await ExecuteXcodeCommandAsync ( "simctl" , "list" , log , TimeSpan . FromSeconds ( 10 ) ) ;
2016-06-17 18:21:18 +03:00
}
2017-11-28 16:27:31 +03:00
public async Task < LogFile > SymbolicateCrashReportAsync ( Logs logs , Log log , LogFile report )
2016-06-17 18:21:18 +03:00
{
var symbolicatecrash = Path . Combine ( XcodeRoot , "Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash" ) ;
if ( ! File . Exists ( symbolicatecrash ) )
symbolicatecrash = Path . Combine ( XcodeRoot , "Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash" ) ;
if ( ! File . Exists ( symbolicatecrash ) ) {
log . WriteLine ( "Can't symbolicate {0} because the symbolicatecrash script {1} does not exist" , report . Path , symbolicatecrash ) ;
return report ;
}
2017-11-28 16:27:31 +03:00
var name = Path . GetFileName ( report . Path ) ;
2019-05-28 15:25:50 +03:00
var symbolicated = logs . Create ( Path . ChangeExtension ( name , ".symbolicated.log" ) , $"Symbolicated crash report: {name}" , timestamp : false ) ;
2016-06-17 18:21:18 +03:00
var environment = new Dictionary < string , string > { { "DEVELOPER_DIR" , Path . Combine ( XcodeRoot , "Contents" , "Developer" ) } } ;
2017-06-06 23:32:25 +03:00
var rv = await ProcessHelper . ExecuteCommandAsync ( symbolicatecrash , StringUtils . Quote ( report . Path ) , symbolicated , TimeSpan . FromMinutes ( 1 ) , environment ) ;
2016-06-17 18:21:18 +03:00
if ( rv . Succeeded ) { ;
log . WriteLine ( "Symbolicated {0} successfully." , report . Path ) ;
return symbolicated ;
} else {
log . WriteLine ( "Failed to symbolicate {0}." , report . Path ) ;
return report ;
}
}
2016-10-11 20:30:11 +03:00
public async Task < HashSet < string > > CreateCrashReportsSnapshotAsync ( Log log , bool simulatorOrDesktop , string device )
2016-06-17 18:21:18 +03:00
{
var rv = new HashSet < string > ( ) ;
2016-06-29 19:21:03 +03:00
if ( simulatorOrDesktop ) {
2016-06-17 18:21:18 +03:00
var dir = Path . Combine ( Environment . GetEnvironmentVariable ( "HOME" ) , "Library" , "Logs" , "DiagnosticReports" ) ;
if ( Directory . Exists ( dir ) )
rv . UnionWith ( Directory . EnumerateFiles ( dir ) ) ;
} else {
var tmp = Path . GetTempFileName ( ) ;
try {
2016-10-11 20:30:11 +03:00
var sb = new StringBuilder ( ) ;
2017-06-06 23:32:25 +03:00
sb . Append ( " --list-crash-reports=" ) . Append ( StringUtils . Quote ( tmp ) ) ;
sb . Append ( " --sdkroot " ) . Append ( StringUtils . Quote ( XcodeRoot ) ) ;
2016-10-11 20:30:11 +03:00
if ( ! string . IsNullOrEmpty ( device ) )
2017-06-06 23:32:25 +03:00
sb . Append ( " --devname " ) . Append ( StringUtils . Quote ( device ) ) ;
2016-10-11 20:30:11 +03:00
var result = await ProcessHelper . ExecuteCommandAsync ( MlaunchPath , sb . ToString ( ) , log , TimeSpan . FromMinutes ( 1 ) ) ;
2016-06-17 18:21:18 +03:00
if ( result . Succeeded )
rv . UnionWith ( File . ReadAllLines ( tmp ) ) ;
} finally {
File . Delete ( tmp ) ;
}
}
return rv ;
}
2018-11-23 18:02:15 +03:00
2016-05-26 16:06:52 +03:00
}
2016-06-29 19:21:03 +03:00
public class CrashReportSnapshot
{
public Harness Harness { get ; set ; }
public Log Log { get ; set ; }
public Logs Logs { get ; set ; }
public string LogDirectory { get ; set ; }
public bool Device { get ; set ; }
2016-10-11 20:30:11 +03:00
public string DeviceName { get ; set ; }
2016-06-29 19:21:03 +03:00
public HashSet < string > InitialSet { get ; private set ; }
public IEnumerable < string > Reports { get ; private set ; }
public async Task StartCaptureAsync ( )
{
2016-10-11 20:30:11 +03:00
InitialSet = await Harness . CreateCrashReportsSnapshotAsync ( Log , ! Device , DeviceName ) ;
2016-06-29 19:21:03 +03:00
}
public async Task EndCaptureAsync ( TimeSpan timeout )
{
// Check for crash reports
var crash_report_search_done = false ;
var crash_report_search_timeout = timeout . TotalSeconds ;
var watch = new Stopwatch ( ) ;
watch . Start ( ) ;
do {
2016-10-11 20:30:11 +03:00
var end_crashes = await Harness . CreateCrashReportsSnapshotAsync ( Log , ! Device , DeviceName ) ;
2016-06-29 19:21:03 +03:00
end_crashes . ExceptWith ( InitialSet ) ;
Reports = end_crashes ;
if ( end_crashes . Count > 0 ) {
Log . WriteLine ( "Found {0} new crash report(s)" , end_crashes . Count ) ;
List < LogFile > crash_reports ;
if ( ! Device ) {
crash_reports = new List < LogFile > ( end_crashes . Count ) ;
foreach ( var path in end_crashes ) {
2017-11-28 16:27:31 +03:00
Logs . AddFile ( path , $"Crash report: {Path.GetFileName (path)}" ) ;
2016-06-29 19:21:03 +03:00
}
} else {
// Download crash reports from the device. We put them in the project directory so that they're automatically deleted on wrench
// (if we put them in /tmp, they'd never be deleted).
var downloaded_crash_reports = new List < LogFile > ( ) ;
foreach ( var file in end_crashes ) {
2017-11-28 16:27:31 +03:00
var name = Path . GetFileName ( file ) ;
2019-05-28 15:25:50 +03:00
var crash_report_target = Logs . Create ( name , $"Crash report: {name}" , timestamp : false ) ;
2016-10-11 20:30:11 +03:00
var sb = new StringBuilder ( ) ;
2017-06-06 23:32:25 +03:00
sb . Append ( " --download-crash-report=" ) . Append ( StringUtils . Quote ( file ) ) ;
sb . Append ( " --download-crash-report-to=" ) . Append ( StringUtils . Quote ( crash_report_target . Path ) ) ;
sb . Append ( " --sdkroot " ) . Append ( StringUtils . Quote ( Harness . XcodeRoot ) ) ;
2016-10-11 20:30:11 +03:00
if ( ! string . IsNullOrEmpty ( DeviceName ) )
2017-06-06 23:32:25 +03:00
sb . Append ( " --devname " ) . Append ( StringUtils . Quote ( DeviceName ) ) ;
2016-10-11 20:30:11 +03:00
var result = await ProcessHelper . ExecuteCommandAsync ( Harness . MlaunchPath , sb . ToString ( ) , Log , TimeSpan . FromMinutes ( 1 ) ) ;
2016-06-29 19:21:03 +03:00
if ( result . Succeeded ) {
Log . WriteLine ( "Downloaded crash report {0} to {1}" , file , crash_report_target . Path ) ;
2017-11-28 16:27:31 +03:00
crash_report_target = await Harness . SymbolicateCrashReportAsync ( Logs , Log , crash_report_target ) ;
2016-06-29 19:21:03 +03:00
downloaded_crash_reports . Add ( crash_report_target ) ;
} else {
Log . WriteLine ( "Could not download crash report {0}" , file ) ;
}
}
crash_reports = downloaded_crash_reports ;
}
foreach ( var cp in crash_reports ) {
Harness . LogWrench ( "@MonkeyWrench: AddFile: {0}" , cp . Path ) ;
Log . WriteLine ( " {0}" , cp . Path ) ;
}
crash_report_search_done = true ;
} else {
if ( watch . Elapsed . TotalSeconds > crash_report_search_timeout ) {
crash_report_search_done = true ;
} else {
Log . WriteLine ( "No crash reports, waiting a second to see if the crash report service just didn't complete in time ({0})" , ( int ) ( crash_report_search_timeout - watch . Elapsed . TotalSeconds ) ) ;
Thread . Sleep ( TimeSpan . FromSeconds ( 1 ) ) ;
}
}
} while ( ! crash_report_search_done ) ;
}
}
2016-05-26 16:06:52 +03:00
}