Skip to content
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

[dotnet] Added tests, fixed bugs #17979

Merged
merged 7 commits into from
Apr 14, 2023
Merged

Conversation

stephen-hawley
Copy link
Contributor

Stunt testing!

What happens is this: we write a string of C# to a file. This C# acts as a mock of the ObjCRuntime namespace it also includes a one or more classes that act internally like NSObject descendants at least as far as the class_ptr field is concerned.

The test compiles this code, runs the rewriter, then executes the final code collecting the output.
The tests include the following:

  1. tool not run, code works as expected
  2. tool run, ClassHandle now returns a different value
  3. tool run, a class not listed for changing stays the same
  4. tool run on a more authentic cctor, the cctor gets removed entirely

The code to run a process and collect its output was taken from the binding-tools-for-swift tests.

All tests pass.

@stephen-hawley stephen-hawley added not-notes-worthy Ignore for release notes dotnet An issue or pull request related to .NET (6) labels Apr 5, 2023
@stephen-hawley stephen-hawley self-assigned this Apr 5, 2023
@github-actions
Copy link
Contributor

github-actions bot commented Apr 5, 2023

⚠️ Your code has been reformatted. ⚠️

If this is not desired, add the actions-disable-autoformat label, and revert the reformatting commit.

If files unrelated to your change were modified, try reverting the reformatting commit + merging with the target branch (and push those changes).

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

Copy link
Contributor

@tj-devel709 tj-devel709 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few very small things, but otherwise LGTM :)

Directory.CreateDirectory (path);
return path;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

nit: reformatter may grab this :)

if (workingDirectory != null)
info.WorkingDirectory = workingDirectory;

if (output == null)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (output == null)
if (output is null)

info.RedirectStandardInput = false;
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
if (workingDirectory != null)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (workingDirectory != null)
if (workingDirectory is not null)

if (output == null)
output = new StringBuilder ();

if (env != null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (env != null) {
if (env is not null) {


if (env != null) {
foreach (var kvp in env) {
if (kvp.Value == null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (kvp.Value == null) {
if (kvp.Value is null) {

Comment on lines 36 to 42
static string GetTempDirectory ()
{
var unique = Interlocked.Increment (ref counter).ToString ();
var path = Path.Combine (root, unique);
Directory.CreateDirectory (path);
return path;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Cache.CreateTemporaryDirectory instead:

public static string CreateTemporaryDirectory (string? name = null)

Comment on lines 44 to 139
public static string Run (string path, string args, string? workingDirectory = null, bool verbose = false)
{
var output = new StringBuilder ();
var exitCode = RunCommand (path, args, output: output, verbose: verbose, workingDirectory: workingDirectory);
if (exitCode != 0)
throw new Exception ($"Failed to execute (exit code {exitCode}): {path} {string.Join (" ", args)}\n{output.ToString ()}");
return output.ToString ();
}

static void ReadStream (Stream stream, StringBuilder sb, ManualResetEvent completed)
{
var encoding = Encoding.UTF8;
var decoder = encoding.GetDecoder ();
var buffer = new byte [1024];
var characters = new char [encoding.GetMaxCharCount (buffer.Length)];

AsyncCallback? callback = null;
callback = new AsyncCallback ((IAsyncResult ar) => {
var read = stream.EndRead (ar);

var chars = decoder.GetChars (buffer, 0, read, characters, 0);
lock (sb)
sb.Append (characters, 0, chars);

if (read > 0) {
stream.BeginRead (buffer, 0, buffer.Length, callback, null);
} else {
completed.Set ();
}
});
stream.BeginRead (buffer, 0, buffer.Length, callback, null);
}

public static int RunCommand (string path, string args, IDictionary<string, string>? env = null, StringBuilder? output = null, bool verbose = false, string? workingDirectory = null)
{
var info = new ProcessStartInfo (path, args);
info.UseShellExecute = false;
info.RedirectStandardInput = false;
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
if (workingDirectory is not null)
info.WorkingDirectory = workingDirectory;

if (output is null)
output = new StringBuilder ();

if (env is not null) {
foreach (var kvp in env) {
if (kvp.Value is null) {
if (info.EnvironmentVariables.ContainsKey (kvp.Key))
info.EnvironmentVariables.Remove (kvp.Key);
} else {
info.EnvironmentVariables [kvp.Key] = kvp.Value;
}
}
}

if (verbose) {
var envOut = new StringBuilder ();
foreach (var k in info.EnvironmentVariables.Keys) {
if (k is string key) {
var value = info.EnvironmentVariables [key];
envOut.AppendLine ($"export {key}={value}");
}
}
envOut.AppendLine ($"{path} {args}");
Console.Write (envOut.ToString ());
Console.WriteLine ("{0} {1}", path, args);
}

using (var p = Process.Start (info)) {
var error_output = new StringBuilder ();
var stdout_completed = new ManualResetEvent (false);
var stderr_completed = new ManualResetEvent (false);

ReadStream (p.StandardOutput.BaseStream, output, stdout_completed);
ReadStream (p.StandardError.BaseStream, error_output, stderr_completed);

p.WaitForExit ();

stderr_completed.WaitOne (TimeSpan.FromMinutes (1));
stdout_completed.WaitOne (TimeSpan.FromMinutes (1));

if (verbose) {
if (output.Length > 0)
Console.WriteLine (output);
if (error_output.Length > 0)
Console.WriteLine (error_output);
if (p.ExitCode != 0)
Console.Error.WriteLine ($"Process exited with code {p.ExitCode}");
}
if (p.ExitCode != 0 && error_output.Length > 0)
output.Append (error_output);
return p.ExitCode;
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the Execution class in tools/common/Execution.cs instead:

public static Task<Execution> RunAsync (string filename, IList<string> arguments, Dictionary<string, string?>? environment = null, bool mergeOutput = false, string? workingDirectory = null, TextWriter? log = null, TimeSpan? timeout = null, CancellationToken? cancellationToken = null)
{
var standardOutput = new StringWriter ();
var standardError = mergeOutput ? standardOutput : new StringWriter ();
return RunAsync (filename, arguments, environment, standardOutput, standardError, log, workingDirectory, timeout, cancellationToken);
}

Comment on lines 40 to 52
static void DeleteDirectoryAndContents (string path)
{
var directories = new Stack<string> ();
directories.Push (path);
while (directories.Count > 0) {
var currDirectory = directories.Pop ();
PushAll (directories, Directory.EnumerateDirectories (currDirectory));
foreach (var file in Directory.EnumerateFiles (currDirectory))
File.Delete (file);
Directory.Delete (currDirectory);
}
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unnecessary if you use Cache.CreateTemporaryDirectory (as suggested below)

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

Comment on lines 20 to 22
using var writer = new StreamWriter (inputpath);
writer.Write (code);
writer.Flush ();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is somewhat simpler:

Suggested change
using var writer = new StreamWriter (inputpath);
writer.Write (code);
writer.Flush ();
File.WriteAllText (inputPath, code);

@stephen-hawley stephen-hawley merged commit 7f82266 into xamarin:main Apr 14, 2023
@stephen-hawley stephen-hawley deleted the moar-tests branch April 14, 2023 14:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dotnet An issue or pull request related to .NET (6) not-notes-worthy Ignore for release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants