From 420d249aedca6a6669ef33228e47e68ae201a8af Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 2 Nov 2017 17:21:51 -0500 Subject: [PATCH 1/8] [tests] started switching over Builder logging logic Thinking we can run assertions as the stdout events are coming through, and also append to file at the same time. Hoping this will speed up the tests overall and fix the deadlocking issue on Windows when the stdout buffer is full. See https://stackoverflow.com/questions/139593/processstartinfo-hanging-on-waitforexit-why --- .../Xamarin.ProjectTools/Common/Assertion.cs | 32 +++++++ .../Xamarin.ProjectTools/Common/Builder.cs | 94 ++++++++++--------- .../Xamarin.ProjectTools.csproj | 1 + 3 files changed, 84 insertions(+), 43 deletions(-) create mode 100644 src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Assertion.cs diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Assertion.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Assertion.cs new file mode 100644 index 00000000000..1fba2399db5 --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Assertion.cs @@ -0,0 +1,32 @@ +using System; +using System.Linq.Expressions; + +namespace Xamarin.ProjectTools +{ + public class Assertion + { + readonly Expression> expression; + Func func; + + public bool Passed { get; private set; } + + public Assertion (Expression> expression) + { + this.expression = expression; + } + + public void Assert(string line) + { + if (!Passed) { + if (func == null) + func = expression.Compile (); + Passed = func (line); + } + } + + public override string ToString () + { + return expression.Body.ToString (); + } + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs index 90741e1077f..d0ac1e9d8d4 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs @@ -14,11 +14,12 @@ public class Builder : IDisposable public bool IsUnix { get; set; } public bool RunningMSBuild { get; set; } public LoggerVerbosity Verbosity { get; set; } - public string LastBuildOutput { get; set; } public TimeSpan LastBuildTime { get; protected set; } public string BuildLogFile { get; set; } public bool ThrowOnBuildFailure { get; set; } + public List Assertions { get; set; } = new List (); + string GetVisualStudio2017Directory () { var editions = new [] { @@ -187,11 +188,6 @@ protected bool BuildInternal (string projectOrSolution, string target, string [] ? Path.GetFullPath (Path.Combine (Root, Path.GetDirectoryName (projectOrSolution), BuildLogFile)) : null; - var logger = buildLogFullPath == null - ? string.Empty - : string.Format ("/noconsolelogger \"/flp1:LogFile={0};Encoding=UTF-8;Verbosity={1}\"", - buildLogFullPath, Verbosity.ToString ().ToLower ()); - var start = DateTime.UtcNow; var homeDirectory = Environment.GetFolderPath (Environment.SpecialFolder.Personal); var androidSdkToolPath = Path.Combine (homeDirectory, "android-toolchain"); @@ -208,8 +204,8 @@ protected bool BuildInternal (string projectOrSolution, string target, string [] var args = new StringBuilder (); var psi = new ProcessStartInfo (XABuildExe); - args.AppendFormat ("{0} /t:{1} {2}", - QuoteFileName(Path.Combine (Root, projectOrSolution)), target, logger); + args.AppendFormat ("{0} /t:{1} /v:{2}", + QuoteFileName(Path.Combine (Root, projectOrSolution)), target, Verbosity); if (RunningMSBuild) args.Append (" /p:BuildingOutOfProcess=true"); else @@ -246,48 +242,60 @@ protected bool BuildInternal (string projectOrSolution, string target, string [] bool result = false; int attempts = 1; for (int attempt = 0; attempt < attempts; attempt++) { - var p = Process.Start (psi); - var ranToCompletion = p.WaitForExit ((int)new TimeSpan (0, 10, 0).TotalMilliseconds); - result = ranToCompletion && p.ExitCode == 0; - - LastBuildTime = DateTime.UtcNow - start; - - var sb = new StringBuilder (); - sb.AppendLine (psi.FileName + " " + args.ToString () + Environment.NewLine); - if (!ranToCompletion) - sb.AppendLine ("Build Timed Out!"); - if (buildLogFullPath != null && File.Exists (buildLogFullPath)) { - using (var fs = File.OpenRead (buildLogFullPath)) { - using (var sr = new StreamReader (fs, Encoding.UTF8, true, 65536)) { - string line; - while ((line = sr.ReadLine ()) != null) { - sb.AppendLine (line); - if (line.StartsWith ("Time Elapsed", StringComparison.OrdinalIgnoreCase)) { - var match = timeElapsedRegEx.Match (line); - if (match.Success) { - LastBuildTime = TimeSpan.Parse (match.Groups ["TimeSpan"].Value); - Console.WriteLine ($"Found Time Elapsed {LastBuildTime}"); - } - } - if (line.StartsWith ("Got a SIGSEGV while executing native code", StringComparison.OrdinalIgnoreCase)) { - nativeCrashDetected = true; - break; - } + using (var p = new Process { StartInfo = psi }) { + + p.OutputDataReceived += (sender, e) => { + + if (e.Data.StartsWith ("Time Elapsed", StringComparison.OrdinalIgnoreCase)) { + var match = timeElapsedRegEx.Match (e.Data); + if (match.Success) { + LastBuildTime = TimeSpan.Parse (match.Groups ["TimeSpan"].Value); + Console.WriteLine ($"Found Time Elapsed {LastBuildTime}"); + } + } + + if (e.Data.StartsWith ("Got a SIGSEGV while executing native code", StringComparison.OrdinalIgnoreCase)) { + nativeCrashDetected = true; + } + + foreach (var assertion in Assertions) { + assertion.Assert (e.Data); + } + }; + + p.BeginOutputReadLine (); + p.BeginErrorReadLine (); + + var ranToCompletion = p.WaitForExit ((int)new TimeSpan (0, 10, 0).TotalMilliseconds); + result = ranToCompletion && p.ExitCode == 0; + + LastBuildTime = DateTime.UtcNow - start; + + var sb = new StringBuilder (); + sb.AppendLine (psi.FileName + " " + args.ToString () + Environment.NewLine); + if (!ranToCompletion) + sb.AppendLine ("Build Timed Out!"); + if (buildLogFullPath != null && File.Exists (buildLogFullPath)) { + using (var fs = File.OpenRead (buildLogFullPath)) { + using (var sr = new StreamReader (fs, Encoding.UTF8, true, 65536)) { + string line; + while ((line = sr.ReadLine ()) != null) { + sb.AppendLine (line); + } } } - } - sb.AppendFormat ("\n#stdout begin\n{0}\n#stdout end\n", p.StandardOutput.ReadToEnd ()); - sb.AppendFormat ("\n#stderr begin\n{0}\n#stderr end\n", p.StandardError.ReadToEnd ()); + sb.AppendFormat ("\n#stdout begin\n{0}\n#stdout end\n", p.StandardOutput.ReadToEnd ()); + sb.AppendFormat ("\n#stderr begin\n{0}\n#stderr end\n", p.StandardError.ReadToEnd ()); - LastBuildOutput = sb.ToString (); - if (nativeCrashDetected) { - Console.WriteLine ($"Native crash detected! Running the build for {projectOrSolution} again."); - continue; + LastBuildOutput = sb.ToString (); + if (nativeCrashDetected) { + Console.WriteLine ($"Native crash detected! Running the build for {projectOrSolution} again."); + continue; + } } } - if (buildLogFullPath != null) { Directory.CreateDirectory (Path.GetDirectoryName (buildLogFullPath)); File.WriteAllText (buildLogFullPath, LastBuildOutput); diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Xamarin.ProjectTools.csproj b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Xamarin.ProjectTools.csproj index 0aa46a15113..d2512b5dd32 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Xamarin.ProjectTools.csproj +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Xamarin.ProjectTools.csproj @@ -40,6 +40,7 @@ + From c853d621bb6a58b05c2ed78500a28ce1e98bb538 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 3 Nov 2017 11:33:16 -0500 Subject: [PATCH 2/8] [tests] a few tests working now with assertion changes Goal is to get AndroidUpdateResourcesTests refactored/passing There are 44 of these and this seems like a good trial run --- .../AndroidUpdateResourcesTest.cs | 60 ++++--- .../Utilities/BaseTest.cs | 9 ++ .../Xamarin.ProjectTools/Common/Assertion.cs | 13 +- .../Common/BuildOutput.cs | 26 +-- .../Xamarin.ProjectTools/Common/Builder.cs | 148 ++++++++++++------ .../Xamarin.ProjectTools.csproj | 2 +- 6 files changed, 163 insertions(+), 95 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs index bd2905b787d..d484f859014 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs @@ -27,11 +27,15 @@ public void RepetitiveBuild () b.Verbosity = Microsoft.Build.Framework.LoggerVerbosity.Diagnostic; b.ThrowOnBuildFailure = false; Assert.IsTrue (b.Build (proj), "first build failed"); + + b.AssertTargetSkipped ("_Sign"); Assert.IsTrue (b.Build (proj), "second build failed"); - Assert.IsTrue (b.Output.IsTargetSkipped ("_Sign"), "failed to skip some build"); + AssertBuild (b); + + b.AssertTargetIsBuilt ("_Sign"); proj.AndroidResources.First ().Timestamp = null; // means "always build" Assert.IsTrue (b.Build (proj), "third build failed"); - Assert.IsFalse (b.Output.IsTargetSkipped ("_Sign"), "incorrectly skipped some build"); + AssertBuild (b); } } @@ -85,10 +89,13 @@ public void DesignTimeBuild ([Values(false, true)] bool isRelease, [Values (fals b.Verbosity = LoggerVerbosity.Diagnostic; b.ThrowOnBuildFailure = false; b.Target = "Compile"; + if (useManagedParser) + b.Assertions.Add (new Assertion (o => o.Contains ("Skipping GetAdditionalResourcesFromAssemblies"), "failed to skip the downloading of files.")); + else + b.Assertions.Add (new Assertion (o => !o.Contains ("Skipping GetAdditionalResourcesFromAssemblies"), "failed to skip the downloading of files.")); Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true, parameters: new string [] { "DesignTimeBuild=true" }, environmentVariables: envVar), "first build failed"); - Assert.AreEqual (!useManagedParser, b.LastBuildOutput.Contains ("Skipping GetAdditionalResourcesFromAssemblies"), - "failed to skip the downloading of files."); + AssertBuild (b); var items = new List (); string first = null; if (!useManagedParser) { @@ -539,9 +546,10 @@ public void CheckAaptErrorRaisedForMissingResource () using (var b = CreateApkBuilder (Path.Combine (projectPath, "UnamedApp"), false, false)) { b.Verbosity = LoggerVerbosity.Diagnostic; b.ThrowOnBuildFailure = false; + b.Assertions.Add (new Assertion (o => o.Contains ("APT0000: "))); + b.Assertions.Add (new Assertion (o => o.Contains ("2 Error(s)"))); Assert.IsFalse (b.Build (proj), "Build should have failed"); - StringAssert.Contains ("APT0000: ", b.LastBuildOutput); - StringAssert.Contains ("2 Error(s)", b.LastBuildOutput); + AssertBuild (b); } } @@ -558,9 +566,10 @@ public void CheckAaptErrorRaisedForInvalidDirectoryName () using (var b = CreateApkBuilder (Path.Combine (projectPath, "UnamedApp"), false, false)) { b.Verbosity = LoggerVerbosity.Diagnostic; b.ThrowOnBuildFailure = false; + b.Assertions.Add (new Assertion (o => o.Contains ("APT0000: "))); + b.Assertions.Add (new Assertion (o => o.Contains ("1 Error(s)"))); Assert.IsFalse (b.Build (proj), "Build should have failed"); - StringAssert.Contains ("APT0000: ", b.LastBuildOutput); - StringAssert.Contains ("1 Error(s)", b.LastBuildOutput); + AssertBuild (b); } } @@ -575,9 +584,10 @@ public void CheckAaptErrorRaisedForInvalidFileName () using (var b = CreateApkBuilder (Path.Combine (projectPath, "UnamedApp"), false, false)) { b.Verbosity = LoggerVerbosity.Diagnostic; b.ThrowOnBuildFailure = false; + b.Assertions.Add (new Assertion (o => o.Contains ("Invalid file name:"))); + b.Assertions.Add (new Assertion (o => o.Contains ("1 Error(s)"))); Assert.IsFalse (b.Build (proj), "Build should have failed"); - StringAssert.Contains ("Invalid file name:", b.LastBuildOutput); - StringAssert.Contains ("1 Error(s)", b.LastBuildOutput); + AssertBuild (b); } } @@ -597,9 +607,11 @@ public void CheckAaptErrorRaisedForDuplicateResourceinApp () using (var b = CreateApkBuilder (Path.Combine (projectPath, "UnamedApp"), false, false)) { b.Verbosity = LoggerVerbosity.Diagnostic; b.ThrowOnBuildFailure = false; + + b.Assertions.Add (new Assertion (o => o.Contains ("APT0000: "))); + b.Assertions.Add (new Assertion (o => o.Contains ("2 Error(s)"))); Assert.IsFalse (b.Build (proj), "Build should have failed"); - StringAssert.Contains ("APT0000: ", b.LastBuildOutput); - StringAssert.Contains ("2 Error(s)", b.LastBuildOutput); + AssertBuild (b); } } @@ -916,25 +928,30 @@ public string GetFoo () { Assert.IsTrue (libBuilder.Build (libProj), "Library project should have built"); using (var appBuilder = CreateApkBuilder (Path.Combine (path, appProj.ProjectName), false, false)) { appBuilder.Verbosity = LoggerVerbosity.Diagnostic; + appBuilder.AssertTargetIsBuilt ("_UpdateAndroidResgen"); Assert.IsTrue (appBuilder.Build (appProj), "Application Build should have succeeded."); - Assert.IsFalse (appBuilder.Output.IsTargetSkipped ("_UpdateAndroidResgen"), "_UpdateAndroidResgen target not should be skipped."); + AssertBuild (appBuilder); foo.Timestamp = DateTime.UtcNow; + libBuilder.AssertTargetSkipped ("_AddLibraryProjectsEmbeddedResourceToProject"); Assert.IsTrue (libBuilder.Build (libProj, doNotCleanupOnUpdate: true, saveProject: false), "Library project should have built"); - Assert.IsTrue (libBuilder.Output.IsTargetSkipped ("_AddLibraryProjectsEmbeddedResourceToProject"), "_AddLibraryProjectsEmbeddedResourceToProject should be skipped."); + AssertBuild (libBuilder); + appBuilder.AssertTargetSkipped ("_UpdateAndroidResgen"); Assert.IsTrue (appBuilder.Build (appProj, doNotCleanupOnUpdate: true, saveProject: false), "Application Build should have succeeded."); - Assert.IsTrue (appBuilder.Output.IsTargetSkipped ("_UpdateAndroidResgen"), "_UpdateAndroidResgen target should be skipped."); + AssertBuild (appBuilder); theme.TextContent = () => @" #00000000 #ffffffff "; theme.Timestamp = DateTime.UtcNow; + libBuilder.AssertTargetIsBuilt ("_AddLibraryProjectsEmbeddedResourceToProject"); Assert.IsTrue (libBuilder.Build (libProj, doNotCleanupOnUpdate: true, saveProject: false), "Library project should have built"); - Assert.IsFalse (libBuilder.Output.IsTargetSkipped ("_AddLibraryProjectsEmbeddedResourceToProject"), "_AddLibraryProjectsEmbeddedResourceToProject should not be skipped."); + AssertBuild (libBuilder); + appBuilder.AssertTargetIsBuilt ("_UpdateAndroidResgen"); Assert.IsTrue (appBuilder.Build (appProj, doNotCleanupOnUpdate: true, saveProject: false), "Application Build should have succeeded."); + AssertBuild (appBuilder); string text = File.ReadAllText (Path.Combine (Root, path, appProj.ProjectName, "Resources", "Resource.designer.cs")); Assert.IsTrue (text.Contains ("theme_devicedefault_background2"), "Resource.designer.cs was not updated."); - Assert.IsFalse (appBuilder.Output.IsTargetSkipped ("_UpdateAndroidResgen"), "_UpdateAndroidResgen target should NOT be skipped."); theme.Deleted = true; theme.Timestamp = DateTime.UtcNow; Assert.IsTrue (libBuilder.Build (libProj, saveProject: true), "Library project should have built"); @@ -958,10 +975,10 @@ public void BuildAppWithManagedResourceParser() using (var appBuilder = CreateApkBuilder (Path.Combine (path, appProj.ProjectName))) { appBuilder.Verbosity = LoggerVerbosity.Diagnostic; appBuilder.Target = "Compile"; + appBuilder.AssertTargetIsBuilt ("_ManagedUpdateAndroidResgen"); Assert.IsTrue (appBuilder.Build (appProj, parameters: new string[] { "DesignTimeBuild=true", "BuildingInsideVisualStudio=true" } ), "DesignTime Application Build should have succeeded."); - Assert.IsFalse (appProj.CreateBuildOutput (appBuilder).IsTargetSkipped ("_ManagedUpdateAndroidResgen"), - "Target '_ManagedUpdateAndroidResgen' should have run."); + AssertBuild (appBuilder); var designerFile = Path.Combine (Root, path, appProj.ProjectName, appProj.IntermediateOutputPath, "designtime", "Resource.Designer.cs"); FileAssert.Exists (designerFile, $"'{designerFile}' should have been created."); @@ -972,14 +989,13 @@ public void BuildAppWithManagedResourceParser() StringAssert.Contains ("Icon", designerContents, $"{designerFile} should contain Resources.Drawable.Icon"); StringAssert.Contains ("Main", designerContents, $"{designerFile} should contain Resources.Layout.Main"); appBuilder.Target = "SignAndroidPackage"; + appBuilder.AssertTargetSkipped ("_ManagedUpdateAndroidResgen"); Assert.IsTrue (appBuilder.Build (appProj), "Normal Application Build should have succeeded."); - Assert.IsTrue (appProj.CreateBuildOutput (appBuilder).IsTargetSkipped ("_ManagedUpdateAndroidResgen"), - "Target '_ManagedUpdateAndroidResgen' should not have run."); + AssertBuild (appBuilder); Assert.IsTrue (appBuilder.Clean (appProj), "Clean should have succeeded"); Assert.IsFalse (File.Exists (designerFile), $"'{designerFile}' should have been cleaned."); - } } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs index 361e16fccbe..1686d9ed007 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs @@ -177,6 +177,15 @@ protected ProjectBuilder CreateDllBuilder (string directory, bool cleanupAfterSu return BuildHelper.CreateDllBuilder (directory, cleanupAfterSuccessfulBuild, cleanupOnDispose); } + protected void AssertBuild(ProjectBuilder builder) + { + foreach (var assertion in builder.Assertions) { + if (!assertion.Passed) { + Assert.Fail (assertion.ToString ()); + } + } + } + [OneTimeSetUp] public void FixtureSetup () { diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Assertion.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Assertion.cs index 1fba2399db5..245e939b28b 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Assertion.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Assertion.cs @@ -3,6 +3,9 @@ namespace Xamarin.ProjectTools { + /// + /// Represents an "assertion" that a condition is true as the build output streams through a callback + /// public class Assertion { readonly Expression> expression; @@ -10,9 +13,12 @@ public class Assertion public bool Passed { get; private set; } - public Assertion (Expression> expression) + public string Message { get; private set; } + + public Assertion (Expression> expression, string message = null) { this.expression = expression; + Message = message; } public void Assert(string line) @@ -26,7 +32,10 @@ public void Assert(string line) public override string ToString () { - return expression.Body.ToString (); + if (!string.IsNullOrEmpty (Message)) + return Message; + + return $"Expression was false: {expression.Body}"; } } } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/BuildOutput.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/BuildOutput.cs index 0bef5cd05c9..70cd326f2cd 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/BuildOutput.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/BuildOutput.cs @@ -44,30 +44,10 @@ public string GetIntermediaryAsText (string file) return File.ReadAllText (GetIntermediaryPath (file)); } - public bool IsTargetSkipped (string target) + //TODO: remove + public bool IsTargetSkipped (string a) { - if (!Builder.LastBuildOutput.Contains (target)) - throw new ArgumentException (string.Format ("Target '{0}' is not even in the build output.", target)); - return Builder.LastBuildOutput.Contains (string.Format ("Target {0} skipped due to ", target)) - || Builder.LastBuildOutput.Contains (string.Format ("Skipping target \"{0}\" because it has no outputs.", target)) - || Builder.LastBuildOutput.Contains (string.Format ("Target \"{0}\" skipped, due to", target)) - || Builder.LastBuildOutput.Contains (string.Format ("Skipping target \"{0}\" because its outputs are up-to-date", target)) - || Builder.LastBuildOutput.Contains (string.Format ("target {0}, skipping", target)) - || Builder.LastBuildOutput.Contains ($"Skipping target \"{target}\" because all output files are up-to-date"); - } - - public bool IsApkInstalled { - get { return Builder.LastBuildOutput.Contains (" pm install "); } - } - - public bool AreTargetsAllSkipped (params string [] targets) - { - return targets.All (t => IsTargetSkipped (t)); - } - - public bool AreTargetsAllBuilt (params string [] targets) - { - return targets.All (t => !IsTargetSkipped (t)); + throw new NotImplementedException (); } } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs index d0ac1e9d8d4..8f57ef71d3d 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs @@ -18,8 +18,56 @@ public class Builder : IDisposable public string BuildLogFile { get; set; } public bool ThrowOnBuildFailure { get; set; } + //TODO: remove + public string LastBuildOutput { + get { throw new NotImplementedException (); } + } + public List Assertions { get; set; } = new List (); + public void AssertTargetSkipped (string target) + { + Assertions.Add (new Assertion (o => o.Contains (target), $"Target '{target}' is not even in the build output.")); + + Assertions.Add (new Assertion (o => o.Contains ($"Target {target} skipped due to ") || + o.Contains ($"Skipping target \"{target}\" because it has no outputs.") || + o.Contains ($"Target \"{target}\" skipped, due to") || + o.Contains ($"Skipping target \"{target}\" because its outputs are up-to-date") || + o.Contains ($"target {target}, skipping") || + o.Contains ($"Skipping target \"{target}\" because all output files are up-to-date"), $"Target {target} was not skipped.")); + } + + public void AssertApkInstalled () + { + Assertions.Add (new Assertion (o => o.Contains (" pm install "))); + } + + public void AssertAllTargetsSkipped (params string [] targets) + { + foreach (var t in targets) { + AssertTargetSkipped (t); + } + } + + public void AssertTargetIsBuilt (string target) + { + Assertions.Add (new Assertion (o => o.Contains (target), $"Target '{target}' is not even in the build output.")); + + Assertions.Add (new Assertion (o => !o.Contains ($"Target {target} skipped due to ") && + !o.Contains ($"Skipping target \"{target}\" because it has no outputs.") && + !o.Contains ($"Target \"{target}\" skipped, due to") && + !o.Contains ($"Skipping target \"{target}\" because its outputs are up-to-date") && + !o.Contains ($"target {target}, skipping") && + !o.Contains ($"Skipping target \"{target}\" because all output files are up-to-date"), $"Target {target} was not built.")); + } + + public void AssertAllTargetsBuilt (params string [] targets) + { + foreach (var t in targets) { + AssertTargetIsBuilt (t); + } + } + string GetVisualStudio2017Directory () { var editions = new [] { @@ -240,69 +288,75 @@ protected bool BuildInternal (string projectOrSolution, string target, string [] bool nativeCrashDetected = false; bool result = false; + bool lastBuildTimeSet = false; int attempts = 1; for (int attempt = 0; attempt < attempts; attempt++) { using (var p = new Process { StartInfo = psi }) { + StreamWriter file = null; + if (buildLogFullPath != null) { + Directory.CreateDirectory (Path.GetDirectoryName (buildLogFullPath)); + file = File.CreateText (buildLogFullPath); + } + try { + var standardError = new StringBuilder (); + file?.WriteLine ("#stdout begin"); + + p.OutputDataReceived += (sender, e) => { + if (e.Data == null) + return; + if (e.Data.StartsWith ("Time Elapsed", StringComparison.OrdinalIgnoreCase)) { + var match = timeElapsedRegEx.Match (e.Data); + if (match.Success) { + LastBuildTime = TimeSpan.Parse (match.Groups ["TimeSpan"].Value); + lastBuildTimeSet = true; + Console.WriteLine ($"Found Time Elapsed {LastBuildTime}"); + } + } - p.OutputDataReceived += (sender, e) => { + if (e.Data.StartsWith ("Got a SIGSEGV while executing native code", StringComparison.OrdinalIgnoreCase)) { + nativeCrashDetected = true; + } - if (e.Data.StartsWith ("Time Elapsed", StringComparison.OrdinalIgnoreCase)) { - var match = timeElapsedRegEx.Match (e.Data); - if (match.Success) { - LastBuildTime = TimeSpan.Parse (match.Groups ["TimeSpan"].Value); - Console.WriteLine ($"Found Time Elapsed {LastBuildTime}"); + foreach (var assertion in Assertions) { + assertion.Assert (e.Data); } - } - if (e.Data.StartsWith ("Got a SIGSEGV while executing native code", StringComparison.OrdinalIgnoreCase)) { - nativeCrashDetected = true; - } + file?.WriteLine (e.Data); + }; + p.ErrorDataReceived += (sender, e) => standardError.AppendLine (e.Data); + + p.Start (); + p.BeginOutputReadLine (); + p.BeginErrorReadLine (); - foreach (var assertion in Assertions) { - assertion.Assert (e.Data); + var ranToCompletion = p.WaitForExit ((int)new TimeSpan (0, 10, 0).TotalMilliseconds); + if (nativeCrashDetected) { + Console.WriteLine ($"Native crash detected! Running the build for {projectOrSolution} again."); + continue; } - }; - - p.BeginOutputReadLine (); - p.BeginErrorReadLine (); - - var ranToCompletion = p.WaitForExit ((int)new TimeSpan (0, 10, 0).TotalMilliseconds); - result = ranToCompletion && p.ExitCode == 0; - - LastBuildTime = DateTime.UtcNow - start; - - var sb = new StringBuilder (); - sb.AppendLine (psi.FileName + " " + args.ToString () + Environment.NewLine); - if (!ranToCompletion) - sb.AppendLine ("Build Timed Out!"); - if (buildLogFullPath != null && File.Exists (buildLogFullPath)) { - using (var fs = File.OpenRead (buildLogFullPath)) { - using (var sr = new StreamReader (fs, Encoding.UTF8, true, 65536)) { - string line; - while ((line = sr.ReadLine ()) != null) { - sb.AppendLine (line); - - } + result = ranToCompletion && p.ExitCode == 0; + if (!lastBuildTimeSet) + LastBuildTime = DateTime.UtcNow - start; + + if (file != null) { + file.WriteLine (); + file.WriteLine ("#stdout end"); + file.WriteLine (); + file.WriteLine ("#stderr begin"); + file.WriteLine (standardError.ToString ()); + file.WriteLine ("#stderr end"); } - } - sb.AppendFormat ("\n#stdout begin\n{0}\n#stdout end\n", p.StandardOutput.ReadToEnd ()); - sb.AppendFormat ("\n#stderr begin\n{0}\n#stderr end\n", p.StandardError.ReadToEnd ()); - - LastBuildOutput = sb.ToString (); - if (nativeCrashDetected) { - Console.WriteLine ($"Native crash detected! Running the build for {projectOrSolution} again."); - continue; + } finally { + file?.Dispose (); } } } - if (buildLogFullPath != null) { - Directory.CreateDirectory (Path.GetDirectoryName (buildLogFullPath)); - File.WriteAllText (buildLogFullPath, LastBuildOutput); - } if (!result && ThrowOnBuildFailure) { string message = "Build failure: " + Path.GetFileName (projectOrSolution) + (BuildLogFile != null && File.Exists (buildLogFullPath) ? "Build log recorded at " + buildLogFullPath : null); - throw new FailedBuildException (message, null, LastBuildOutput); + + //TODO: do we really need the full build log here? It seems to lock up my VS test runner + throw new FailedBuildException (message, null); } return result; diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Xamarin.ProjectTools.csproj b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Xamarin.ProjectTools.csproj index d2512b5dd32..42ab8d720de 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Xamarin.ProjectTools.csproj +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Xamarin.ProjectTools.csproj @@ -40,8 +40,8 @@ - + From da966701657ba75565a875ab61d435e0fe71447a Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 3 Nov 2017 11:44:56 -0500 Subject: [PATCH 3/8] [tests] hack in TearDown for Windows Temporary hack. It would be better to figure out what is causing this and remove thsi commit. --- .../Utilities/BaseTest.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs index 1686d9ed007..5b5add4674d 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs @@ -224,8 +224,17 @@ protected virtual void CleanupTest () return; if (TestContext.CurrentContext.Result.Outcome.Status == NUnit.Framework.Interfaces.TestStatus.Passed || TestContext.CurrentContext.Result.Outcome.Status == NUnit.Framework.Interfaces.TestStatus.Skipped) { - FileSystemUtils.SetDirectoryWriteable (output); - Directory.Delete (output, recursive: true); + + do { + try { + FileSystemUtils.SetDirectoryWriteable (output); + Directory.Delete (output, recursive: true); + break; + } catch (IOException) { + //NOTE: seems to happen quite a bit on Windows + Thread.Sleep (25); + } + } while (true); } else { foreach (var file in Directory.GetFiles (Path.Combine (output), "build.log", SearchOption.AllDirectories)) { TestContext.Out.WriteLine ("*************************************************************************"); From 86705c71c9f8d7b22fc23c4a8cf9e64793032935 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 3 Nov 2017 12:02:08 -0500 Subject: [PATCH 4/8] [tests] a couple more fixed --- .../AndroidUpdateResourcesTest.cs | 24 +++++++++---------- .../Utilities/BaseTest.cs | 9 +++++++ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs index d484f859014..475e81e8f24 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs @@ -353,7 +353,9 @@ protected override void OnClick() proj.SetProperty (proj.ReleaseProperties, "JavaMaximumHeapSize", "1G"); using (var b = CreateApkBuilder (Path.Combine (projectPath))) { b.Verbosity = LoggerVerbosity.Diagnostic; + b.Assertions.Add (new Assertion (o => o.Contains ("AndroidResgen: Warning while updating Resource XML"), "Warning while processing resources should not have been raised.")); Assert.IsTrue (b.Build (proj), "Build should have succeeded."); + AssertBuildDidNotPass (b); var preferencesPath = Path.Combine (Root, projectPath, proj.IntermediateOutputPath, "res","xml","preferences.xml"); Assert.IsTrue (File.Exists (preferencesPath), "Preferences.xml should have been renamed to preferences.xml"); var doc = XDocument.Load (preferencesPath); @@ -375,8 +377,6 @@ protected override void OnClick() .FirstOrDefault (x => x.Attribute("name").Value == "colorAccent"); Assert.IsNotNull (item, "The Style should contain an Item"); Assert.AreEqual ("@color/deep_purple_A200", item.Value, "item value should be @color/deep_purple_A200"); - StringAssert.DoesNotContain ("AndroidResgen: Warning while updating Resource XML", b.LastBuildOutput, - "Warning while processing resources should not have been raised."); Assert.IsTrue (b.Clean (proj), "Clean should have succeeded."); } } @@ -1044,15 +1044,15 @@ public void BuildAppWithManagedResourceParserAndLibraries () appBuilder.Verbosity = LoggerVerbosity.Diagnostic; appBuilder.ThrowOnBuildFailure = false; libBuilder.Target = "Compile"; + libBuilder.AssertTargetIsBuilt ("_ManagedUpdateAndroidResgen"); Assert.IsTrue (libBuilder.Build (libProj, parameters: new string [] { "DesignTimeBuild=true", "BuildingInsideVisualStudio=true" }), "Library project should have built"); Assert.LessOrEqual (libBuilder.LastBuildTime.TotalMilliseconds, maxBuildTimeMs, $"DesignTime build should be less than {maxBuildTimeMs} milliseconds."); - Assert.IsFalse (libProj.CreateBuildOutput (libBuilder).IsTargetSkipped ("_ManagedUpdateAndroidResgen"), - "Target '_ManagedUpdateAndroidResgen' should have run."); + AssertBuild (libBuilder); appBuilder.Target = "Compile"; - Assert.AreEqual (!appBuilder.RunningMSBuild, appBuilder.Build (appProj, parameters: new string [] { "DesignTimeBuild=true", "BuildingInsideVisualStudio=true" }), "Application project should have built"); + appBuilder.AssertTargetIsBuilt ("_ManagedUpdateAndroidResgen"); + Assert.IsTrue(appBuilder.Build (appProj, parameters: new string [] { "DesignTimeBuild=true", "BuildingInsideVisualStudio=true" }), "Application project should have built"); Assert.LessOrEqual (appBuilder.LastBuildTime.TotalMilliseconds, maxBuildTimeMs, $"DesignTime build should be less than {maxBuildTimeMs} milliseconds."); - Assert.IsFalse (appProj.CreateBuildOutput (appBuilder).IsTargetSkipped ("_ManagedUpdateAndroidResgen"), - "Target '_ManagedUpdateAndroidResgen' should have run."); + AssertBuild (appBuilder); var designerFile = Path.Combine (Root, path, appProj.ProjectName, appProj.IntermediateOutputPath, "designtime", "Resource.Designer.cs"); FileAssert.Exists (designerFile, $"'{designerFile}' should have been created."); @@ -1065,14 +1065,14 @@ public void BuildAppWithManagedResourceParserAndLibraries () StringAssert.Contains ("material_grey_50", designerContents, $"{designerFile} should contain Resources.Color.material_grey_50"); StringAssert.DoesNotContain ("theme_devicedefault_background", designerContents, $"{designerFile} should not contain Resources.Color.theme_devicedefault_background"); libBuilder.Target = "Build"; + libBuilder.AssertTargetSkipped ("_ManagedUpdateAndroidResgen"); Assert.IsTrue (libBuilder.Build (libProj), "Library project should have built"); - Assert.IsTrue (libProj.CreateBuildOutput (libBuilder).IsTargetSkipped ("_ManagedUpdateAndroidResgen"), - "Target '_ManagedUpdateAndroidResgen' should not have run."); + AssertBuild (libBuilder); appBuilder.Target = "Compile"; + appBuilder.AssertTargetIsBuilt ("_ManagedUpdateAndroidResgen"); Assert.IsTrue (appBuilder.Build (appProj, parameters: new string [] { "DesignTimeBuild=true", "BuildingInsideVisualStudio=true" }), "App project should have built"); + AssertBuild (appBuilder); Assert.LessOrEqual (appBuilder.LastBuildTime.TotalMilliseconds, maxBuildTimeMs, $"DesignTime build should be less than {maxBuildTimeMs} milliseconds."); - Assert.IsFalse (appProj.CreateBuildOutput (appBuilder).IsTargetSkipped ("_ManagedUpdateAndroidResgen"), - "Target '_ManagedUpdateAndroidResgen' should have run."); FileAssert.Exists (designerFile, $"'{designerFile}' should have been created."); designerContents = File.ReadAllText (designerFile); @@ -1094,8 +1094,6 @@ public void BuildAppWithManagedResourceParserAndLibraries () designerFile = Path.Combine (Root, path, libProj.ProjectName, libProj.IntermediateOutputPath, "designtime", "Resource.Designer.cs"); Assert.IsTrue (libBuilder.Clean (libProj), "Clean should have succeeded"); Assert.IsFalse (File.Exists (designerFile), $"'{designerFile}' should have been cleaned."); - - } } } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs index 5b5add4674d..7fbb9ec615b 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs @@ -186,6 +186,15 @@ protected void AssertBuild(ProjectBuilder builder) } } + protected void AssertBuildDidNotPass (ProjectBuilder builder) + { + foreach (var assertion in builder.Assertions) { + if (assertion.Passed) { + Assert.Fail (assertion.ToString ()); + } + } + } + [OneTimeSetUp] public void FixtureSetup () { From d04ac6ab94ca19b6879d233ca58889e8fd709cac Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 3 Nov 2017 12:12:05 -0500 Subject: [PATCH 5/8] [tests] fixed DesignTimeBuild tests --- .../AndroidUpdateResourcesTest.cs | 15 ++++++++------- .../Utilities/BaseTest.cs | 2 ++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs index 475e81e8f24..11244d00666 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs @@ -89,13 +89,13 @@ public void DesignTimeBuild ([Values(false, true)] bool isRelease, [Values (fals b.Verbosity = LoggerVerbosity.Diagnostic; b.ThrowOnBuildFailure = false; b.Target = "Compile"; - if (useManagedParser) - b.Assertions.Add (new Assertion (o => o.Contains ("Skipping GetAdditionalResourcesFromAssemblies"), "failed to skip the downloading of files.")); - else - b.Assertions.Add (new Assertion (o => !o.Contains ("Skipping GetAdditionalResourcesFromAssemblies"), "failed to skip the downloading of files.")); + b.Assertions.Add (new Assertion (o => o.Contains ("Skipping GetAdditionalResourcesFromAssemblies"), "failed to skip the downloading of files.")); Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true, parameters: new string [] { "DesignTimeBuild=true" }, environmentVariables: envVar), "first build failed"); - AssertBuild (b); + if (useManagedParser) + AssertBuildDidNotPass (b); + else + AssertBuild (b); var items = new List (); string first = null; if (!useManagedParser) { @@ -108,9 +108,10 @@ public void DesignTimeBuild ([Values(false, true)] bool isRelease, [Values (fals } WaitFor (1000); b.Target = "Build"; + b.AssertTargetIsBuilt ("_BuildAdditionalResourcesCache"); + b.Assertions.Add (new Assertion (o => o.Contains ($"Downloading {url}") || o.Contains ($"reusing existing archive: {zipPath}"))); Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true, parameters: new string [] { "DesignTimeBuild=false" }, environmentVariables: envVar), "second build failed"); - Assert.IsFalse(b.Output.IsTargetSkipped ("_BuildAdditionalResourcesCache"), "_BuildAdditionalResourcesCache should have run."); - Assert.IsTrue (b.LastBuildOutput.Contains ($"Downloading {url}") || b.LastBuildOutput.Contains ($"reusing existing archive: {zipPath}"), $"{url} should have been downloaded."); + AssertBuild (b); Assert.IsTrue (File.Exists (Path.Combine (extractedDir, "1", "content", "android-N", "aapt")), $"Files should have been extracted to {extractedDir}"); items.Clear (); if (!useManagedParser) { diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs index 7fbb9ec615b..5f542c5c3ed 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs @@ -184,6 +184,7 @@ protected void AssertBuild(ProjectBuilder builder) Assert.Fail (assertion.ToString ()); } } + builder.Assertions.Clear (); } protected void AssertBuildDidNotPass (ProjectBuilder builder) @@ -193,6 +194,7 @@ protected void AssertBuildDidNotPass (ProjectBuilder builder) Assert.Fail (assertion.ToString ()); } } + builder.Assertions.Clear (); } [OneTimeSetUp] From 5bb23b9c8b9640bd870999f56db26a1cfe33bd37 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 3 Nov 2017 12:18:31 -0500 Subject: [PATCH 6/8] [tests] fixed two more --- .../AndroidUpdateResourcesTest.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs index 11244d00666..ef36ebd5c10 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs @@ -165,9 +165,10 @@ public void MoveResource () var oldpath = image.Include ().Replace ('\\', Path.DirectorySeparatorChar); image.Include = () => "Resources/drawable/NewImage.png"; image.Timestamp = DateTimeOffset.UtcNow.AddMinutes (1); + b.AssertTargetIsBuilt ("_Sign"); Assert.IsTrue (b.Build (proj), "Second build should have succeeded."); + AssertBuild (b); Assert.IsFalse (File.Exists (Path.Combine (b.ProjectDirectory, oldpath)), "XamarinProject.UpdateProjectFiles() failed to delete file"); - Assert.IsFalse (b.Output.IsTargetSkipped ("_Sign"), "incorrectly skipped some build"); } } @@ -178,8 +179,9 @@ public void ReportAaptErrorsInOriginalFileName () proj.LayoutMain = @"\n" + proj.LayoutMain; using (var b = CreateApkBuilder ("temp/ErroneousResource")) { b.ThrowOnBuildFailure = false; + b.Assertions.Add (new Assertion (o => o.Contains (string.Format ("Resources{0}layout{0}Main.axml", Path.DirectorySeparatorChar)) && o.Contains (": error "), "error with expected file name is not found")); Assert.IsFalse (b.Build (proj), "Build should have failed."); - Assert.IsTrue (b.LastBuildOutput.Split ('\n').Any (s => s.Contains (string.Format ("Resources{0}layout{0}Main.axml", Path.DirectorySeparatorChar)) && s.Contains (": error ")), "error with expected file name is not found"); + AssertBuild (b); Assert.IsTrue (b.Clean (proj), "Clean should have succeeded."); } } From 7be483f7d5845ef9b7e992c5461ad30ac934d8a1 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 3 Nov 2017 12:24:04 -0500 Subject: [PATCH 7/8] [tests] fixed one more --- .../AndroidUpdateResourcesTest.cs | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs index ef36ebd5c10..9d3f3bc020a 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs @@ -204,27 +204,18 @@ public void RepetiviteBuildUpdateSingleResource () b.ThrowOnBuildFailure = false; Assert.IsTrue (b.Build (proj), "First build was supposed to build without errors"); var firstBuildTime = b.LastBuildTime; + b.AssertTargetSkipped ("_GenerateAndroidResourceDir"); + b.AssertTargetSkipped ("_CompileJava"); Assert.IsTrue (b.Build (proj), "Second build was supposed to build without errors"); + AssertBuild (b); Assert.IsTrue (firstBuildTime > b.LastBuildTime, "Second build was supposed to be quicker than the first"); - Assert.IsTrue ( - b.Output.IsTargetSkipped ("_GenerateAndroidResourceDir"), - "The Target _GenerateAndroidResourceDir should have been skipped"); - Assert.IsTrue ( - b.Output.IsTargetSkipped ("_CompileJava"), - "The Target _CompileJava should have been skipped"); image1.Timestamp = DateTime.UtcNow; var layout = proj.AndroidResources.First (x => x.Include() == "Resources\\layout\\Main.axml"); layout.Timestamp = DateTime.UtcNow; + b.AssertTargetIsBuilt ("_GenerateAndroidResourceDir"); + b.AssertTargetSkipped ("_CompileJava"); + b.AssertTargetIsBuilt ("_CreateBaseApk"); Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate:true, saveProject: false), "Third build was supposed to build without errors"); - Assert.IsFalse ( - b.Output.IsTargetSkipped ("_GenerateAndroidResourceDir"), - "The Target _GenerateAndroidResourceDir should not have been skipped"); - Assert.IsTrue ( - b.Output.IsTargetSkipped ("_CompileJava"), - "The Target _CompileJava (2) should have been skipped"); - Assert.IsFalse ( - b.Output.IsTargetSkipped ("_CreateBaseApk"), - "The Target _CreateBaseApk should not have been skipped"); } } From 67fede03811e5a5858a72f83ffcad67f6af2be5d Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 3 Nov 2017 15:02:51 -0500 Subject: [PATCH 8/8] [tests] fix TargetGenerateJavaDesignerForComponentIsSkipped --- .../AndroidUpdateResourcesTest.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs index 9d3f3bc020a..d554b0019a9 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs @@ -500,21 +500,21 @@ public void TargetGenerateJavaDesignerForComponentIsSkipped ([Values(false, true proj.SetProperty ("TargetFrameworkVersion", "v5.0"); using (var b = CreateApkBuilder (Path.Combine ("temp", TestContext.CurrentContext.Test.Name))) { b.Verbosity = LoggerVerbosity.Diagnostic; + b.AssertTargetIsBuilt ("_GenerateJavaDesignerForComponent"); Assert.IsTrue (b.Build (proj), "Build should have succeeded."); - StringAssert.DoesNotContain ("Skipping target \"_GenerateJavaDesignerForComponent\" because", - b.LastBuildOutput, "Target _GenerateJavaDesignerForComponent should not have been skipped"); + AssertBuild (b); + b.AssertAllTargetsSkipped ("_GenerateJavaDesignerForComponent"); Assert.IsTrue (b.Build (proj), "Build should have succeeded."); - StringAssert.Contains ("Skipping target \"_GenerateJavaDesignerForComponent\" because", - b.LastBuildOutput, "Target _GenerateJavaDesignerForComponent should have been skipped"); + AssertBuild (b); var files = Directory.EnumerateFiles (Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "resourcecache") , "abc_fade_in.xml", SearchOption.AllDirectories); Assert.AreEqual (1, files.Count (), "There should only be one abc_fade_in.xml in the resourcecache"); var resFile = files.First (); Assert.IsTrue (File.Exists (resFile), "{0} should exist", resFile); File.SetLastWriteTime (resFile, DateTime.UtcNow); + b.AssertTargetIsBuilt ("_GenerateJavaDesignerForComponent"); Assert.IsTrue (b.Build (proj), "Build should have succeeded."); - StringAssert.DoesNotContain ("Skipping target \"_GenerateJavaDesignerForComponent\" because", - b.LastBuildOutput, "Target _GenerateJavaDesignerForComponent should not have been skipped"); + AssertBuild (b); } }