Problem
The EnvironmentFilesParser class in src/Xamarin.Android.Build.Tasks/Utilities/EnvironmentFilesParser.cs has no unit tests. It contains non-trivial parsing logic for Android environment configuration files — detecting log levels, GC params, mono debug settings, HTTP handlers, assembly preload, and broken exception transitions — that should be covered by tests to prevent regressions.
Location
- File:
src/Xamarin.Android.Build.Tasks/Utilities/EnvironmentFilesParser.cs
- Test directory:
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/
Current Code
The class parses environment variable files line by line, setting boolean flags and collecting lines:
class EnvironmentFilesParser
{
public bool BrokenExceptionTransitions { get; set; }
public bool HaveHttpMessageHandler { get; private set; }
public bool HaveLogLevel { get; private set; }
public bool HaveMonoDebug { get; private set; }
public bool HaveMonoGCParams { get; private set; }
public bool HaveTlsProvider { get; private set; }
public bool UsesAssemblyPreload { get; set; }
public List<string> EnvironmentVariableLines { get; } = new List<string> ();
public bool AreBrokenExceptionTransitionsEnabled (ITaskItem[] environments) { ... }
public void Parse (ITaskItem[]? environments, SequencePointsMode sequencePointsMode, TaskLoggingHelper log) { ... }
}
Suggested Fix
Create a new test file src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/EnvironmentFilesParserTests.cs with tests covering the following behaviors. The class is internal but accessible via [InternalsVisibleTo("Xamarin.Android.Build.Tests")] in Properties/AssemblyInfo.cs.
Tests should create temporary files with specific environment variable content and verify the parser sets the correct flags.
Test cases to cover:
MONO_LOG_LEVEL= detection — Verify HaveLogLevel is set to true when a line starts with MONO_LOG_LEVEL=
MONO_GC_PARAMS= detection — Verify HaveMonoGCParams is set to true
MONO_GC_PARAMS= with old bridge warning — Verify that when the line contains bridge-implementation=old, the parser logs coded warning XA2000
MONO_DEBUG= detection — Verify HaveMonoDebug is set to true
MONO_DEBUG= with sequence points — When sequencePointsMode != SequencePointsMode.None and the line does not contain gen-compact-seq-points, verify that gen-compact-seq-points is appended to the line in EnvironmentVariableLines
XA_HTTP_CLIENT_HANDLER_TYPE= detection — Verify HaveHttpMessageHandler is set to true
mono.enable_assembly_preload= handling — Verify UsesAssemblyPreload is set; note this line should NOT appear in EnvironmentVariableLines (it's filtered via continue)
XA_BROKEN_EXCEPTION_TRANSITIONS= handling — Verify BrokenExceptionTransitions is set; note this line should NOT appear in EnvironmentVariableLines (it's filtered via continue)
AreBrokenExceptionTransitionsEnabled — Verify it returns true when a file contains a XA_BROKEN_EXCEPTION_TRANSITIONS= line, and false otherwise
- Empty/null environments — Verify
Parse handles null environments parameter without throwing
- Multiple files — Verify flags are accumulated across multiple environment files
Example structure:
using System.Collections.Generic;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using NUnit.Framework;
using Xamarin.Android.Tasks;
namespace Xamarin.Android.Build.Tests
{
[TestFixture]
[Parallelizable (ParallelScope.Self)]
public class EnvironmentFilesParserTests : BaseTest
{
string? tempDirectory;
[SetUp]
public void Setup ()
{
tempDirectory = Path.Combine (Path.GetTempPath (), Path.GetRandomFileName ());
Directory.CreateDirectory (tempDirectory);
}
[TearDown]
public void TearDown ()
{
if (tempDirectory != null && Directory.Exists (tempDirectory))
Directory.Delete (tempDirectory, recursive: true);
}
ITaskItem CreateEnvFile (string content)
{
var path = Path.Combine (tempDirectory!, Path.GetRandomFileName () + ".env");
File.WriteAllText (path, content);
return new TaskItem (path);
}
[Test]
public void DetectsMonoLogLevel ()
{
var envFile = CreateEnvFile ("MONO_LOG_LEVEL=debug");
var parser = new EnvironmentFilesParser ();
var engine = new MockBuildEngine (TestContext.Out);
var log = new TaskLoggingHelper (engine, "Test");
parser.Parse (new [] { envFile }, SequencePointsMode.None, log);
Assert.IsTrue (parser.HaveLogLevel);
}
[Test]
public void MonoGCParams_OldBridgeWarning ()
{
var envFile = CreateEnvFile ("MONO_GC_PARAMS=bridge-implementation=old");
var warnings = new List<BuildWarningEventArgs> ();
var engine = new MockBuildEngine (TestContext.Out, warnings: warnings);
var log = new TaskLoggingHelper (engine, "Test");
var parser = new EnvironmentFilesParser ();
parser.Parse (new [] { envFile }, SequencePointsMode.None, log);
Assert.IsTrue (parser.HaveMonoGCParams);
Assert.AreEqual (1, warnings.Count);
Assert.AreEqual ("XA2000", warnings [0].Code);
}
// ... additional tests for each behavior listed above
}
}
Guidelines
- Follow existing test patterns in
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/ (e.g., AndroidComputeResPathsTests.cs)
- Extend
BaseTest, use MockBuildEngine — note: MockBuildEngine constructor accepts (TextWriter output, IList<BuildErrorEventArgs> errors = null, IList<BuildWarningEventArgs> warnings = null, IList<BuildMessageEventArgs> messages = null)
TaskLoggingHelper needs a IBuildEngine and a task name string: new TaskLoggingHelper (engine, "Test")
- Use tabs for indentation, space before
( and [ (Mono style)
- No
! (null-forgiving operator) — declare temp fields as nullable instead
SequencePointsMode enum is defined in Xamarin.Android.Tasks namespace (in Tasks/Aot.cs): None, Normal, Offline
- Create and clean up temp files for each test using
[SetUp] / [TearDown]
Acceptance Criteria
Generated by Nightly Fix Finder for issue #11352 · ● 5.4M · ◷
Problem
The
EnvironmentFilesParserclass insrc/Xamarin.Android.Build.Tasks/Utilities/EnvironmentFilesParser.cshas no unit tests. It contains non-trivial parsing logic for Android environment configuration files — detecting log levels, GC params, mono debug settings, HTTP handlers, assembly preload, and broken exception transitions — that should be covered by tests to prevent regressions.Location
src/Xamarin.Android.Build.Tasks/Utilities/EnvironmentFilesParser.cssrc/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/Current Code
The class parses environment variable files line by line, setting boolean flags and collecting lines:
Suggested Fix
Create a new test file
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/EnvironmentFilesParserTests.cswith tests covering the following behaviors. The class isinternalbut accessible via[InternalsVisibleTo("Xamarin.Android.Build.Tests")]inProperties/AssemblyInfo.cs.Tests should create temporary files with specific environment variable content and verify the parser sets the correct flags.
Test cases to cover:
MONO_LOG_LEVEL=detection — VerifyHaveLogLevelis set totruewhen a line starts withMONO_LOG_LEVEL=MONO_GC_PARAMS=detection — VerifyHaveMonoGCParamsis set totrueMONO_GC_PARAMS=with old bridge warning — Verify that when the line containsbridge-implementation=old, the parser logs coded warningXA2000MONO_DEBUG=detection — VerifyHaveMonoDebugis set totrueMONO_DEBUG=with sequence points — WhensequencePointsMode != SequencePointsMode.Noneand the line does not containgen-compact-seq-points, verify thatgen-compact-seq-pointsis appended to the line inEnvironmentVariableLinesXA_HTTP_CLIENT_HANDLER_TYPE=detection — VerifyHaveHttpMessageHandleris set totruemono.enable_assembly_preload=handling — VerifyUsesAssemblyPreloadis set; note this line should NOT appear inEnvironmentVariableLines(it's filtered viacontinue)XA_BROKEN_EXCEPTION_TRANSITIONS=handling — VerifyBrokenExceptionTransitionsis set; note this line should NOT appear inEnvironmentVariableLines(it's filtered viacontinue)AreBrokenExceptionTransitionsEnabled— Verify it returnstruewhen a file contains aXA_BROKEN_EXCEPTION_TRANSITIONS=line, andfalseotherwiseParsehandlesnullenvironmentsparameter without throwingExample structure:
Guidelines
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/(e.g.,AndroidComputeResPathsTests.cs)BaseTest, useMockBuildEngine— note:MockBuildEngineconstructor accepts(TextWriter output, IList<BuildErrorEventArgs> errors = null, IList<BuildWarningEventArgs> warnings = null, IList<BuildMessageEventArgs> messages = null)TaskLoggingHelperneeds aIBuildEngineand a task name string:new TaskLoggingHelper (engine, "Test")(and[(Mono style)!(null-forgiving operator) — declare temp fields as nullable insteadSequencePointsModeenum is defined inXamarin.Android.Tasksnamespace (inTasks/Aot.cs):None,Normal,Offline[SetUp]/[TearDown]Acceptance Criteria
EnvironmentFilesParserTests.csadded in the Tasks test directoryMONO_LOG_LEVELdetection testedMONO_GC_PARAMSdetection tested, includingXA2000warning for old bridgeMONO_DEBUGdetection and sequence-points appending testedXA_HTTP_CLIENT_HANDLER_TYPEdetection testedXA_BROKEN_EXCEPTION_TRANSITIONSfiltering tested (flag set, line excluded fromEnvironmentVariableLines)mono.enable_assembly_preloadfiltering tested (flag set, line excluded fromEnvironmentVariableLines)AreBrokenExceptionTransitionsEnabledtested