Skip to content

[CI] Use dotnet-test-slicer in nightly tests #8154

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
343 changes: 68 additions & 275 deletions build-tools/automation/azure-pipelines-nightly.yaml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ static CodeBehindTests ()
{
TestProjectRootDirectory = Path.GetFullPath (Path.Combine (XABuildPaths.TopDirectory, "tests", "CodeBehind", "BuildTests"));
CommonSampleLibraryRootDirectory = Path.GetFullPath (Path.Combine (XABuildPaths.TopDirectory, "tests", "CodeBehind", CommonSampleLibraryName));
TestOutputDir = Path.Combine (SetUp.TestDirectoryRoot, "temp", "CodeBehind");
TestOutputDir = Path.Combine (XABuildPaths.TestOutputDirectory, "temp", "CodeBehind");
if (Builder.UseDotNet) {
ProjectName += ".NET";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public bool Build (string projectOrSolution, string target, string [] parameters
static EmbeddedDSOTests ()
{
TestProjectRootDirectory = Path.GetFullPath (Path.Combine (XABuildPaths.TopDirectory, "tests", "EmbeddedDSOs", "EmbeddedDSO"));
TestOutputDir = Path.Combine (SetUp.TestDirectoryRoot, "temp", "EmbeddedDSO");
TestOutputDir = Path.Combine (XABuildPaths.TestOutputDirectory, "temp", "EmbeddedDSO");

produced_binaries = new List <string> {
$"{ProjectAssemblyName}.dll",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,58 +23,9 @@ public class BaseTest
public static ConcurrentDictionary<string, string> TestOutputDirectories = new ConcurrentDictionary<string, string> ();
public static ConcurrentDictionary<string, string> TestPackageNames = new ConcurrentDictionary<string, string> ();

[SetUpFixture]
public class SetUp
{
public static string TestDirectoryRoot {
get;
private set;
}

[OneTimeSetUp]
public void BeforeAllTests ()
{
TestDirectoryRoot = XABuildPaths.TestOutputDirectory;
}

[OneTimeTearDown]
public void AfterAllTests ()
{
if (System.Diagnostics.Debugger.IsAttached)
return;

//NOTE: adb.exe can cause a couple issues on Windows
// 1) it holds a lock on ~/android-toolchain, so a future build that needs to delete/recreate would fail
// 2) the MSBuild <Exec /> task *can* hang until adb.exe exits

try {
RunAdbCommand ("kill-server", true);
} catch (Exception ex) {
Console.Error.WriteLine ("Failed to run adb kill-server: " + ex);
}

//NOTE: in case `adb kill-server` fails, kill the process as a last resort
foreach (var p in Process.GetProcessesByName ("adb.exe"))
p.Kill ();
}

}

protected bool IsWindows => TestEnvironment.IsWindows;

protected bool IsMacOS => TestEnvironment.IsMacOS;

protected bool IsLinux => TestEnvironment.IsLinux;

public string StagingPath {
get { return Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments); }
}

public string Root {
get {
return Path.GetFullPath (SetUp.TestDirectoryRoot);
}
}
public string Root => Path.GetFullPath (XABuildPaths.TestOutputDirectory);

public static bool CommercialBuildAvailable => TestEnvironment.CommercialBuildAvailable;

Expand Down Expand Up @@ -569,6 +520,28 @@ public void TestSetup ()
TestContext.Out.Flush ();
}

[OneTimeTearDown]
protected virtual void AfterAllTests ()
{
if (System.Diagnostics.Debugger.IsAttached)
return;

//NOTE: adb.exe can cause a couple issues on Windows
// 1) it holds a lock on ~/android-toolchain, so a future build that needs to delete/recreate would fail
// 2) the MSBuild <Exec /> task *can* hang until adb.exe exits
if (IsWindows) {
try {
RunAdbCommand ("kill-server", true);
} catch (Exception ex) {
Console.Error.WriteLine ("Failed to run adb kill-server: " + ex);
}

//NOTE: in case `adb kill-server` fails, kill the process as a last resort
foreach (var p in Process.GetProcessesByName ("adb.exe"))
p.Kill ();
}
}

[TearDown]
protected virtual void CleanupTest ()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public void DeviceSetup ()
}

[OneTimeTearDown]
public void DeviceTearDown ()
protected virtual void DeviceTearDown ()
{
if (IsDeviceAttached ()) {
// make sure we are not on a guest user anymore.
Expand Down Expand Up @@ -199,11 +199,16 @@ protected static void RunProjectAndAssert (XamarinAndroidApplicationProject proj
builder.BuildLogFile = logName;
Assert.True (builder.RunTarget (proj, "_Run", doNotCleanupOnUpdate: doNotCleanupOnUpdate, parameters: parameters), "Project should have run.");
} else {
var result = AdbStartActivity ($"{proj.PackageName}/{proj.JavaPackageName}.MainActivity");
Assert.IsTrue (result.Contains ("Starting: Intent { cmp="), $"Attempt to start activity failed with:\n{result}");
StartActivityAndAssert (proj);
}
}

protected static void StartActivityAndAssert (XamarinAndroidApplicationProject proj)
{
var result = AdbStartActivity ($"{proj.PackageName}/{proj.JavaPackageName}.MainActivity");
Assert.IsTrue (result.Contains ("Starting: Intent { cmp="), $"Attempt to start activity failed with:\n{result}");
}

protected TimeSpan ProfileFor (Func<bool> func, TimeSpan? timeout = null)
{
var stopwatch = new Stopwatch ();
Expand Down
108 changes: 54 additions & 54 deletions tests/MSBuildDeviceIntegration/Tests/LocalizationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using Mono.Unix.Native;
using NUnit.Framework;
using NUnit.Framework.Interfaces;
Expand All @@ -16,8 +17,8 @@ namespace Xamarin.Android.Build.Tests
[NonParallelizable]
public class LocalizationTests : DeviceTest
{
static ProjectBuilder builder;
static XamarinAndroidApplicationProject proj;
ProjectBuilder builder;
XamarinAndroidApplicationProject proj;
string localeFileSuffix;

[OneTimeSetUp]
Expand Down Expand Up @@ -60,19 +61,6 @@ public override void SetupTest ()
if (!string.IsNullOrEmpty (localeParam)) {
localeFileSuffix = localeParam.Replace ("/", "-");
}

if (!IsDeviceAttached (refreshCachedValue: true)) {
RestartDevice ();
AssertHasDevices ();
}

// Attempt to reinstall the app that was installed during fixture setup if it is missing
var packageOutput = RunAdbCommand ($"shell pm list packages {proj.PackageName}").Trim ();
var expectedPackageOutput = $"package:{proj.PackageName}";
if (packageOutput != expectedPackageOutput) {
builder.BuildLogFile = $"setup-install-{localeFileSuffix}.log";
Assert.IsTrue (builder.Install (proj), "Install should have succeeded.");
}
}

/// <summary>
Expand All @@ -93,27 +81,22 @@ protected override void CleanupTest ()
}
}

protected override void DeviceTearDown ()
{
}

[OneTimeTearDown]
public void AfterAllTests ()
protected override void AfterAllTests ()
{
string output = Path.Combine (Root, builder?.ProjectDirectory);
if (TestContext.CurrentContext.Result.FailCount == 0 && Directory.Exists (output)) {
try {
Directory.Delete (output, recursive: true);
} catch (IOException ex) {
// This happens on CI occasionally, let's not fail the test
TestContext.Out.WriteLine ($"Failed to delete '{output}': {ex}");
}
}
}


const int LOCALIZATION_NODE_COUNT = 15;
const int LOCALIZATION_RETRY_COUNT = 3;

static object [] GetLocalizationTestCases (int node)
static List<string> GetLocalizationTestInfo ()
{
List<object> tests = new List<object> ();
var tests = new List<string> ();
var ignore = new string [] {
"he-IL", // maps to wi-IL on Android.
"id-ID", // maps to in-ID on Android
Expand All @@ -127,11 +110,14 @@ static object [] GetLocalizationTestCases (int node)
TestContext.WriteLine ($"Ignoring {ci.Name} Localization Test");
continue;
}
tests.Add (new object [] {
ci.Name,
});
tests.Add (ci.Name);
}
return tests;
}

static object [] GetLocalizationTestCases (int node)
{
var tests = GetLocalizationTestInfo ();
return tests.Where (p => tests.IndexOf (p) % LOCALIZATION_NODE_COUNT == node).ToArray ();
}

Expand Down Expand Up @@ -210,41 +196,56 @@ static object [] GetLocalizationTestCases (int node)
[TestCaseSource (nameof (GetLocalizationTestCases), new object [] { 14 })]
public void CheckLocalizationIsCorrectNode15 (string locale) => CheckLocalizationIsCorrect (locale);

[Test]
[Retry (LOCALIZATION_RETRY_COUNT)]
[TestCaseSource (nameof (GetLocalizationTestInfo))]
public void CheckLocalizationIsCorrectWithSlicer (string locale) => CheckLocalizationIsCorrect (locale);


public void CheckLocalizationIsCorrect (string locale)
{
AssertHasDevices ();

// Attempt to reinstall the app that was installed during fixture setup if it is missing
var packageOutput = RunAdbCommand ($"shell pm list packages {proj.PackageName}").Trim ();
var expectedPackageOutput = $"package:{proj.PackageName}";
if (packageOutput != expectedPackageOutput) {
builder.BuildLogFile = $"setup-install-{localeFileSuffix}.log";
Assert.IsTrue (builder.Install (proj), "Install should have succeeded.");
}

RunAdbCommand ($"shell am force-stop --user all {proj.PackageName}");
RunAdbCommand ($"shell am kill --user all {proj.PackageName}");

var appStartupLogcatFile = Path.Combine (Root, builder.ProjectDirectory, $"startup-logcat-{locale.Replace ("/", "-")}.log");
string deviceLocale = RunAdbCommand ("shell getprop persist.sys.locale")?.Trim ();
TestContext.Out.WriteLine ($"test value:{locale}, prop value:{deviceLocale}");

if (deviceLocale != locale) {
for (int attempt = 0; attempt < 5; attempt++) {
TestContext.Out.WriteLine ($"{nameof(CheckLocalizationIsCorrect)}: Setting Locale to {locale}, attempt {attempt}...");
ClearAdbLogcat ();
var rebootLogcatFile = Path.Combine (Root, builder.ProjectDirectory, $"reboot{attempt}-logcat-{locale.Replace ("/", "-")}.log");

// https://developer.android.com/guide/topics/resources/localization#changing-the-emulator-locale-from-the-adb-shell
RunAdbCommand ($"shell \"su root setprop persist.sys.locale {locale};su root stop;sleep 5;su root start;\"");

if (!MonitorAdbLogcat ((l) => {
if (l.Contains ("ActivityManager: Finished processing BOOT_COMPLETED"))
return true;
return false;
}, rebootLogcatFile, timeout: 60)) {
TestContext.Out.WriteLine ($"{nameof(CheckLocalizationIsCorrect)}: wating for boot to complete failed or timed out.");
}
deviceLocale = RunAdbCommand ("shell getprop persist.sys.locale")?.Trim ();
if (deviceLocale == locale) {
break;
}
for (int attempt = 0; attempt < 5; attempt++) {
TestContext.Out.WriteLine ($"{nameof(CheckLocalizationIsCorrect)}: Setting Locale to {locale}, attempt {attempt}...");
ClearAdbLogcat ();
var rebootLogcatFile = Path.Combine (Root, builder.ProjectDirectory, $"reboot{attempt}-logcat-{locale.Replace ("/", "-")}.log");

// https://developer.android.com/guide/topics/resources/localization#changing-the-emulator-locale-from-the-adb-shell
RunAdbCommand ($"shell \"su root setprop persist.sys.locale {locale};su root stop;sleep 5;su root start;\"");

if (!MonitorAdbLogcat ((l) => {
if (l.Contains ("ActivityManager: Finished processing BOOT_COMPLETED"))
return true;
return false;
}, rebootLogcatFile, timeout: 60)) {
TestContext.Out.WriteLine ($"{nameof(CheckLocalizationIsCorrect)}: wating for boot to complete failed or timed out.");
}
deviceLocale = RunAdbCommand ("shell getprop persist.sys.locale")?.Trim ();
if (deviceLocale == locale) {
break;
}
}

Assert.AreEqual (locale, deviceLocale, $"The command to set the device locale to {locale} failed. Current device locale is {deviceLocale}");
ClearAdbLogcat ();
RunAdbCommand ($"shell am force-stop --user all {proj.PackageName}");
RunAdbCommand ($"shell am kill --user all {proj.PackageName}");
RunProjectAndAssert (proj, builder, logName: $"run-{locale.Replace ("/", "-")}.log");
Thread.Sleep (1000);
StartActivityAndAssert (proj);

string logcatSearchString = "Strings.SomeString=";
string expectedLogcatOutput = $"{logcatSearchString}{locale}";
Expand All @@ -271,7 +272,6 @@ public void CheckLocalizationIsCorrect (string locale)
return false;
}, humanizerLogCatFile, timeout:45), $"App output did not contain '{logcatSearchString}'");
Assert.IsTrue (logLine.Contains (expectedLogcatOutput), $"Line '{logLine}' did not contain '{expectedLogcatOutput}'");

}
}
}
Loading