//todo: write unit test for this public static IObservable <UnitTestDiscovered> DiscoverUnitTests(string testDllSelector, string[] args, Func <ITestArena[]> arenas) { return(Rxn.Create <UnitTestDiscovered>(o => { return GetTargets(testDllSelector, args, arenas, null, null) .Do(t => { ListTests(t.Dll, arenas) .Select( tests => { return new UnitTestDiscovered() { Dll = t.Dll, DiscoveredTests = tests.ToArray() }; }) .Do(o.OnNext) .Until(); }) .Subscribe(); //todo fix hanging }) .Publish() .RefCount()); }
private static IObservable <Unit> SelfDestructIf(string[] args) { return(Rxn.Create(() => { var destruct = args.Skip(1).FirstOrDefault().IsNullOrWhiteSpace("fail"); var quiteMode = args.Last().IsNullOrWhiteSpace("nup"); if (!destruct.BasicallyEquals("destruct")) { return; } if (!quiteMode.BasicallyEquals("quite")) { "Please type 'y' to delete ALL BFG DATA under this root".LogDebug(); if (Console.Read() != 'y') { "Aborting".LogDebug(); return; } } Directory.Delete(DataDir, true); "RESET !!!".LogDebug(); }) .FinallyR(() => { theBfg.IsCompleted.OnNext(new Unit()); theBfg.IsCompleted.OnCompleted(); })); }
public static IObservable <StartUnitTest> GetTargetsFromBfc(string bfcFile, IServiceCommandFactory parseTestSyntax, IObservable <UnitTestResult> forParallelExection) { var pattern = bfcFile.Split('/', '\\'); var dir = pattern.Take(pattern.Length - 1).ToStringEach("/"); var filePattern = pattern.Last(); var watchers = new CompositeDisposable(); return(Rxn.Create <StartUnitTest>(o => { Files.WatchForChanges(dir, filePattern, true, false, false).SelectMany(_ => TestWorkflow.StartIntegrationTest(File.ReadAllText(bfcFile), parseTestSyntax, forParallelExection).Do(dll => o.OnNext(dll))) .Until().DisposedBy(watchers); if (bfcFile.EndsWith(".bfc", StringComparison.InvariantCultureIgnoreCase)) { if (!File.Exists(bfcFile)) { $"Could not find theBFG command file: {bfcFile}".LogDebug(); o.OnCompleted(); } TestWorkflow.StartIntegrationTest(File.ReadAllText(bfcFile), parseTestSyntax, forParallelExection).Do(dll => o.OnNext(dll)).Until(); } return watchers; }) ); }
public static IObservable <Unit> ReloadWithTestWorker(params string[] args) { return(Rxn.Create <Unit>(o => { var apiName = args.Skip(1).FirstOrDefault(); var testHostUrl = GetTestarenaUrlFromArgs(args); theBfg.Args = args; RxnExtensions.DeserialiseImpl = (t, json) => JsonExtensions.FromJson(json, t); RxnExtensions.SerialiseImpl = (json) => JsonExtensions.ToJson(json); var cfg = RxnAppCfg.Detect(args); //var appStore = new CurrentDirectoryAppUpdateStore(); //var clusterHost = OutOfProcessFactory.CreateClusterHost(args, appStore, cfg); return theBfgDef.TestWorker(apiName, testHostUrl, RxnApp.SpareReator(testHostUrl)).ToRxns() .Named(new bfgAppInfo("bfgWorker")) .OnHost(new ConsoleHostedApp(), cfg) .SelectMany(h => h.Run().Do(app => { theBfg.IsReady.OnNext(app); })) .Select(app => { return new Unit(); }) .Subscribe(o); })); }
public IObservable <CommandResult> Handle(UntagWorker command) { return(Rxn.Create(() => { Info[bfgTagWorkflow.WorkerTag] = Info[bfgTagWorkflow.WorkerTag].Split(',').Except(command.Tags).ToStringEach(); return CommandResult.Success().AsResultOf(command).ToObservable(); })); }
public IObservable <CommandResult> Handle(TagWorker command) { return(Rxn.Create(() => { Info[bfgTagWorkflow.WorkerTag] = $"{Info[bfgTagWorkflow.WorkerTag]},{command.Tags.ToStringEach()}"; return CommandResult.Success().AsResultOf(command).ToObservable(); })); }
public IObservable <CommandResult> Handle(Reload command) { return(Rxn.Create(() => { "Reloading".LogDebug(); Fire(); return CommandResult.Success().AsResultOf(command); })); }
public static IObservable <Unit> ReloadAnd(string url = "http://*****:*****@test.dll and fire".LogDebug(); "fire".LogDebug(); "fire @url".LogDebug(); "fire rapidly {{threadCount | max}} | will fire on multiple threads simultatiously".LogDebug(); "fire compete | shard test-suite execution across multiple nodes".LogDebug(); "".LogDebug(); "launch [email protected] | deploy apps to worker nodes automatically during CI/CD. Worker integration via complementary C# api: theBfgApi.launch(\"app\", \"dir\")".LogDebug(); "".LogDebug(); "".LogDebug(); "<<USE WITH CAUTION>>".LogDebug(); "".LogDebug(); break; } return Disposable.Empty; })); }
public static IObservable <Unit> ReloadWithTestArena(params string[] args) { return(Rxn.Create <Unit>(o => { ReportStatus.StartupLogger = ReportStatus.Log.ReportToConsole(); theBfg.Args = args; "Configuring App".LogDebug(); theBFGAspNetCoreAdapter.Appcfg = RxnAppCfg.Detect(args); return AspNetCoreWebApiAdapter.StartWebServices <theBFGAspNetCoreAdapter>(theBFGAspNetCoreAdapter.Cfg, args).ToObservable() .LastAsync() .Select(_ => new Unit()) .Subscribe(o); })); }
public IObservable <IRxn> Start(string name, StartUnitTest work, StreamWriter testLog, string logDir) { var testEventStream = new Subject <IRxn>(); //https://github.com/dotnet/sdk/issues/5514 var dotnetHack = PathToTestArenaProcess(); var logName = $"{name}{work.RunThisTest.Substring(0, work.RunThisTest.Length > 25 ? 25 : work.RunThisTest.Length).IsNullOrWhiteSpace(new FileInfo(work.Dll).Name)}".LogDebug("Targeting"); bool isreadingOutputMessage = false; var lastLine = false; OnStart(work); return(Rxn.Create ( dotnetHack, StartTestsCmd(work, logDir), i => { if (i == null) { return; } foreach (var progress in OnLog(name, work, i)) { testEventStream.OnNext(progress); } if (testLog.BaseStream.CanWrite) { testLog.WriteLine(i.LogDebug(logName)); } }, e => testLog.WriteLine(e.LogDebug(logName)) ) .FinallyR(() => { foreach (var e in OnEnd(work.Dll)) { testEventStream.OnNext(e); } testEventStream.OnCompleted(); }) .SelectMany(_ => testEventStream) ); }
} //Hmm this kind of state is bad. i should ditch static on everything? private static IObservable <StartUnitTest> GetTargetsFromPath(string[] args, string testSyntax, Func <ITestArena[]> arena) { var pattern = testSyntax.Split('/', '\\'); var dir = pattern.Take(pattern.Length - 1).ToStringEach("/"); var filePattern = pattern.Last(); var watchers = new CompositeDisposable(); return(Rxn.Create <StartUnitTest>(o => { foreach (var dll in Directory.GetFileSystemEntries(dir, filePattern, SearchOption.AllDirectories).Select(d => d.AsCrossPlatformPath()).Where(NotAFrameworkFile)) { GetTargetsFromDll(args, dll, arena).Do(t => o.OnNext(t)).Until(); } return watchers; })); }
public IObservable <CommandResult> Handle(StopUnitTest command) { return(Rxn.Create(() => { "Stopping all unit tests".LogDebug(); foreach (var worker in _fanoutStrategy.Workers.Values) { try { worker.DoWork?.Dispose(); } catch (Exception e) { $"Failed to stop {worker.Worker.Name} : {e}".LogDebug(); } } return CommandResult.Success().AsResultOf(command); })); }
public IObservable <IEnumerable <string> > ListTests(string dll) { var testArenaProcess = PathToTestArenaProcess(); var tests = new List <string>(); return(Rxn.Create ( testArenaProcess, ListTestsCmd(dll), i => { i.LogDebug(); foreach (var test in OnTestCmdLog(i)) { tests.Add(test); } }, e => $"failed to parse test: {e}".LogDebug() ) .Aggregate(tests.ToObservable(), (a, b) => a) .SelectMany(e => e) ); }
public IObservable <UnitTestResult> DoWork(StartUnitTest work) { work.Dll = work.Dll.EnsureRooted(); var logId = $"{Name.Replace("#", "")}_{++_runId}_{DateTime.Now:dd-MM-yy-hhmmssfff}"; var logDir = Path.Combine(_cfg.AppRoot, "logs", logId).AsCrossPlatformPath(); StreamWriter testLog = null; FileStream logFile = null; return(Rxn.Create(() => //setup dirs for test { if (!Directory.Exists(logDir)) { Directory.CreateDirectory(logDir); } logFile = File.Create(Path.Combine(logDir, "testArena.log")); testLog = new StreamWriter(logFile, leaveOpen: true); }) .SelectMany(_ => //keep the test updated while we are running it { _isBusy.OnNext(true); return RunTestSuiteInTestArena(work, testLog, logDir); }) .LastOrDefaultAsync() .Delay(TimeSpan.FromSeconds(1))//test is finished, wait for log file to unlock .SelectMany(_ => { try { testLog?.Dispose(); logFile?.Dispose(); } catch (Exception e) { $"While closing log {e}".LogDebug(); } //send the log to the return ShipLogForTest(logDir, logId, work.Id); //send logs to testArena }) .Select(_ => //return result of process { return (UnitTestResult) new UnitTestResult() { WasSuccessful = true }.AsResultOf(work); }) .Catch <UnitTestResult, Exception>(e => { return ((UnitTestResult) new UnitTestResult() { WasSuccessful = false }.AsResultOf(work)).ToObservable(); }) .FinallyR(() => { _isBusy.OnNext(false); })); }
public IObservable <CommandResult> Handle(Run command) { var tokens = command.Cmd.Split(' '); var cmd = tokens[0]; var worker = Name; _rxnManager.Publish(new UnitTestsStarted() { TestId = command.Id, At = DateTime.Now, Tests = new[] { cmd }, Worker = "", //_appInfo.Name, WorkerId = worker }).Until(); var unitTestId = Guid.NewGuid().ToString(); _rxnManager.Publish(new UnitTestPartialResult(command.Id, "passed", cmd, "0", worker) { UnitTestId = unitTestId }).Until(); return(Rxn.Create ( RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "cmd" : "/bin/bash", $"{(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "/c" : "-c")} {command.Cmd}", i => { if (i == null) { return; } _rxnManager.Publish(new UnitTestPartialLogResult { LogMessage = i.ToString(), TestId = command.Id, UnitTestId = unitTestId, Worker = worker }).Until(); }, e => { _rxnManager.Publish(new UnitTestPartialLogResult { LogMessage = e.ToString(), TestId = command.Id, UnitTestId = unitTestId, Worker = worker }).Until(); } ) .FinallyR(() => { _rxnManager.Publish(new UnitTestOutcome() { Passed = 1, Failed = 0, InResponseTo = command.Id, UnitTestId = unitTestId, Dll = cmd }).Until(); }) .Select(_ => CommandResult.Success())); }
public IObservable <CommandResult> Handle(StopRecording command) { return(Rxn.Create(() => _isStarted.OnNext(false)).ToObservable().Select(_ => CommandResult.Success($"Recording stopped").AsResultOf(command))); }
public static IObservable <StartUnitTest> StartIntegrationTest(string testExpression, IServiceCommandFactory cmds, IObservable <UnitTestResult> results) { var serial = testExpression.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries).Select(t => t.Trim()).Where(t => !t.IsNullOrWhitespace()).ToArray(); var stageNo = 0; return(Rxn.Create <StartUnitTest>(o => { var resources = new CompositeDisposable(); return serial .SelectMany(cmd => { var stageTrigger = new Subject <Unit>(); var parallel = cmd.Split(',', StringSplitOptions.RemoveEmptyEntries) .SelectMany(t => { var testSytax = t.Split(';', StringSplitOptions.RemoveEmptyEntries); return Enumerable.Range(0, Int32.Parse(testSytax.Skip(1).FirstOrDefault().IsNullOrWhiteSpace("1"), NumberStyles.Any)).Select(_ => testSytax.Length > 0 ? testSytax[0].Trim() : string.Empty); }) .Select(action => { var tokens = action.Split(' ', StringSplitOptions.RemoveEmptyEntries); return cmds.Get(tokens.First(), tokens.Skip(1)); }) .ToArray(); if (parallel.Length < 1) { return new Unit().ToObservable(); } $"Starting stage {++stageNo} with {parallel.Length} tests in parallel".LogDebug(); var expectedResultIds = parallel.Select(t => t.Id).ToList(); results.Synchronize().Where(tr => { if (expectedResultIds.Contains(tr.InResponseTo)) { expectedResultIds.Remove(tr.InResponseTo); } if (expectedResultIds.Count < 1) { $"Stage {stageNo} complete".LogDebug(); stageTrigger.OnNext(new Unit()); stageTrigger.OnCompleted(); return true; } return false; }) .FirstOrDefaultAsync() .Until() .DisposedBy(resources); parallel.ForEach(t => o.OnNext((StartUnitTest)t)); return stageTrigger; }) .Where(_ => stageNo >= serial.Length) .FirstOrDefaultAsync() .Do(_ => o.OnCompleted()) .FinallyR(() => resources.Dispose()) .Until() ; })); }