Skip to content

Commit

Permalink
Fix argument extraction for test client
Browse files Browse the repository at this point in the history
  • Loading branch information
nirinchev committed Jun 17, 2024
1 parent 853b3fc commit 67cc7ab
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 40 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ dotnet_diagnostic.SA1637.severity = none

dotnet_diagnostic.SX1101.severity = warning


resharper_inconsistent_naming_highlighting = none


## Visual Studio generated .editorconfig file with C++ settings.
Expand Down
24 changes: 16 additions & 8 deletions Tests/Realm.Tests/Sync/SyncTestHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ static SyncTestHelpers()
BaseUri = BaasUri ?? new Uri("http://localhost:12345"),
MetadataPersistenceMode = MetadataPersistenceMode.NotEncrypted,
#pragma warning disable CA1837 // Use Environment.ProcessId instead of Process.GetCurrentProcess().Id
BaseFilePath = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), $"rt-sync-{System.Diagnostics.Process.GetCurrentProcess().Id}-{_appCounter++}")).FullName
BaseFilePath = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), $"rt-sync-{Process.GetCurrentProcess().Id}-{_appCounter++}")).FullName
#pragma warning restore CA1837 // Use Environment.ProcessId instead of Process.GetCurrentProcess().Id
};

Expand Down Expand Up @@ -126,33 +126,41 @@ public static async Task<string[]> ExtractBaasSettingsAsync(string[] args)
return remainingArgs;
}

private class LogArgs
{
public string? RealmLogLevel { get; set; }

public string? RealmLogFile { get; set; }
}

public static (string[] RemainingArgs, IDisposable? Logger) SetLoggerFromArgs(string[] args)
{
var (extracted, remaining) = BaasClient.ExtractArguments(args, "realmloglevel", "realmlogfile");
var (extracted, remaining) = BaasClient.ExtractArguments<LogArgs>(args);

if (extracted.TryGetValue("realmloglevel", out var logLevelStr) && Enum.TryParse<LogLevel>(logLevelStr, out var logLevel))
if (!string.IsNullOrEmpty(extracted.RealmLogLevel))
{
var logLevel = (LogLevel)Enum.Parse(typeof(LogLevel), extracted.RealmLogLevel!);
TestHelpers.Output.WriteLine($"Setting log level to {logLevel}");

Logger.LogLevel = logLevel;
}

Logger.AsyncFileLogger? logger = null;
if (extracted.TryGetValue("realmlogfile", out var logFile))
if (!string.IsNullOrEmpty(extracted.RealmLogFile))
{
if (!Process.GetCurrentProcess().ProcessName.ToLower().Contains("testhost"))
{
TestHelpers.Output.WriteLine($"Setting sync logger to file: {logFile}");
TestHelpers.Output.WriteLine($"Setting sync logger to file: {extracted.RealmLogFile}");

// We're running in a test runner, so we need to use the sync logger
Logger.Default = Logger.File(logFile);
Logger.Default = Logger.File(extracted.RealmLogFile!);
}
else
{
TestHelpers.Output.WriteLine($"Setting async logger to file: {logFile}");
TestHelpers.Output.WriteLine($"Setting async logger to file: {extracted.RealmLogFile}");

// We're running standalone (likely on CI), so we use the async logger
Logger.Default = logger = new Logger.AsyncFileLogger(logFile);
Logger.Default = logger = new Logger.AsyncFileLogger(extracted.RealmLogFile!);
}
}

Expand Down
85 changes: 54 additions & 31 deletions Tools/DeployApps/BaasClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,21 @@

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson.Serialization.Serializers;
#if !NETCOREAPP2_1_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif

namespace Baas
{
Expand Down Expand Up @@ -229,39 +229,57 @@ public static async Task<BaasClient> Atlas(Uri baseUri, string differentiator, T
return result;
}

private class BaasArgs
{
public string? BaasaasApiKey { get; set; }

public string? BaasUrl { get; set; }

public string? BaasCluster { get; set; }

public string? BaasApiKey { get; set; }

public string? BaasPrivateApiKey { get; set; }

public string? BaasProjectId { get; set; }

public string BaasDifferentiator { get; set; } = "local";

[MemberNotNullWhen(false, nameof(BaasCluster), nameof(BaasApiKey), nameof(BaasPrivateApiKey), nameof(BaasProjectId))]
public bool UseDocker => BaasCluster == null;
}

public static async Task<(BaasClient? Client, Uri? BaseUrl, string[] RemainingArgs)> CreateClientFromArgs(string[] args, TextWriter output)
{
if (args == null)
{
throw new ArgumentNullException(nameof(args));
}

var (extracted, remaining) = ExtractArguments(args, "baasaas-api-key", "baas-url", "baas-cluster",
"baas-api-key", "baas-private-api-key", "baas-projectid", "baas-differentiator");
var (extracted, remaining) = ExtractArguments<BaasArgs>(args);

var differentiator = extracted.GetValueOrDefault("baas-differentiator", "local");
var differentiator = extracted.BaasDifferentiator;

BaasClient client;
Uri baseUri;

if (extracted.TryGetValue("baasaas-api-key", out var baasaasApiKey) && !string.IsNullOrEmpty(baasaasApiKey))
if (!string.IsNullOrEmpty(extracted.BaasaasApiKey))
{
baseUri = await GetOrDeployContainer(baasaasApiKey, differentiator, output);
baseUri = await GetOrDeployContainer(extracted.BaasaasApiKey!, differentiator, output);
client = await Docker(baseUri, differentiator, output);
}
else
{
if (!extracted.TryGetValue("baasurl", out var baseUrl) || string.IsNullOrEmpty(baseUrl))
if (string.IsNullOrEmpty(extracted.BaasUrl))
{
return (null, null, remaining);
}

baseUri = new Uri(baseUrl);
var baasCluster = extracted.GetValueOrDefault("baascluster");
baseUri = new Uri(extracted.BaasUrl!);

client = string.IsNullOrEmpty(baasCluster)
client = extracted.UseDocker
? await Docker(baseUri, differentiator, output)
: await Atlas(baseUri, differentiator, output, baasCluster!, extracted["baasapikey"], extracted["baasprivateapikey"], extracted["baasprojectid"]);
: await Atlas(baseUri, differentiator, output, extracted.BaasCluster, extracted.BaasApiKey, extracted.BaasPrivateApiKey, extracted.BaasProjectId);
}

return (client, baseUri, remaining);
Expand All @@ -274,16 +292,16 @@ public static async Task TerminateBaasFromArgs(string[] args, TextWriter output)
throw new ArgumentNullException(nameof(args));
}

var (extracted, _) = ExtractArguments(args, "baasaas-api-key", "baas-differentiator");
var (extracted, _) = ExtractArguments<BaasArgs>(args);

var differentiator = extracted.GetValueOrDefault("baas-differentiator", "local");
var differentiator = extracted.BaasDifferentiator;

if (!extracted.TryGetValue("baasaas-api-key", out var baaSaasApiKey) || string.IsNullOrEmpty(baaSaasApiKey))
if (string.IsNullOrEmpty(extracted.BaasaasApiKey))
{
throw new InvalidOperationException("Need a BaaSaas API key to terminate containers");
throw new InvalidOperationException("Need a Baasaas API key to terminate containers");
}

await StopContainer(baaSaasApiKey, differentiator, output);
await StopContainer(extracted.BaasaasApiKey!, differentiator, output);
}

public string GetSyncDatabaseName(string appType = AppConfigType.Default) => $"Sync_{Differentiator}_{appType}";
Expand Down Expand Up @@ -805,36 +823,41 @@ public static HttpContent GetJsonContent(object obj)
return content;
}

public static (Dictionary<string, string> Extracted, string[] RemainingArgs) ExtractArguments(string[] args, params string[] toExtract)
public static (T Extracted, string[] RemainingArgs) ExtractArguments<T>(string[] args)
where T : new()
{
if (args == null)
{
throw new ArgumentNullException(nameof(args));
}

var extracted = new Dictionary<string, string>();
var remainingArgs = new List<string>();
for (var i = 0; i < args.Length; i++)
var argsToExtract = typeof(T).GetProperties().Select(p => (ArgName: GetArgName(p.Name), PropertyInfo: p)).ToArray();
var invalidProps = argsToExtract.Where(p => p.PropertyInfo != typeof(string) || !p.PropertyInfo.CanRead || !p.PropertyInfo.CanWrite).ToArray();
if (invalidProps.Length != 0)
{
if (!toExtract.Any(name => ExtractArg(i, name)))
{
remainingArgs.Add(args[i]);
}
throw new ArgumentException($"Invalid properties: {string.Join(", ", invalidProps.Select(p => p.PropertyInfo.Name))}");
}

return (extracted, remainingArgs.ToArray());
var extracted = new T();
return (extracted, args.Where(a => !argsToExtract.Any(kvp => ExtractArg(a, kvp))).ToArray());

bool ExtractArg(int index, string name)
bool ExtractArg(string arg, (string ArgName, PropertyInfo Info) prop)
{
var arg = args[index];
if (arg.StartsWith($"--{name}="))
if (arg.StartsWith($"--{prop.ArgName}="))
{
extracted[name] = arg.Replace($"--{name}=", string.Empty);
prop.Info.SetValue(extracted, arg.Replace($"--{prop.ArgName}=", string.Empty));
return true;
}

return false;
}

static string GetArgName(string propertyName)
{
return Regex.Replace(propertyName, "(?<!^)([A-Z][a-z]|(?<=[a-z])[A-Z0-9])", "-$1", RegexOptions.Compiled)
.Trim()
.ToLower();
}
}

public class BaasApp
Expand Down

0 comments on commit 67cc7ab

Please sign in to comment.