Пример #1
0
        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;
            })
                   );
        }
Пример #2
0
        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();
            }));
        }
Пример #3
0
 //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());
 }
Пример #4
0
        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);
            }));
        }
Пример #5
0
        public IObservable <CommandResult> Handle(TagWorker command)
        {
            return(Rxn.Create(() =>
            {
                Info[bfgTagWorkflow.WorkerTag] = $"{Info[bfgTagWorkflow.WorkerTag]},{command.Tags.ToStringEach()}";

                return CommandResult.Success().AsResultOf(command).ToObservable();
            }));
        }
Пример #6
0
        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();
            }));
        }
Пример #7
0
        public IObservable <CommandResult> Handle(Reload command)
        {
            return(Rxn.Create(() =>
            {
                "Reloading".LogDebug();
                Fire();

                return CommandResult.Success().AsResultOf(command);
            }));
        }
Пример #8
0
        private static IObservable <string> GetOrCreateWatcher(string testDll)
        {
            var dlld = new FileInfo(testDll);

            if (_watchers.ContainsKey(dlld.FullName))
            {
                return(Rxn.Empty <string>()); //already subscribed to updates
            }
            var watcher = Files.WatchForChanges(dlld.DirectoryName, dlld.Name, true, false, false);

            _watchers.Add(dlld.FullName, watcher);
            return(watcher);
        }
Пример #9
0
        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;
            }));
        }
Пример #10
0
        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);
            }));
        }
Пример #11
0
        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)
                   );
        }
Пример #12
0
        }                                              //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;
            }));
        }
Пример #13
0
        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);
            }));
        }
Пример #14
0
        public static IObservable <StartUnitTest> GetTargets(string testSyntax, string[] args, Func <ITestArena[]> forCompete, IServiceCommandFactory parseTestSyntax, IObservable <UnitTestResult> forParallelExection)
        {
            return(testSyntax.IsNullOrWhitespace() ?
                   Rxn.Empty <StartUnitTest>() :
                   Rxn.DfrCreate <StartUnitTest>(() =>
            {
                if (!(testSyntax.Contains(".dll", StringComparison.InvariantCultureIgnoreCase) ||
                      testSyntax.Contains(".csproj", StringComparison.InvariantCultureIgnoreCase) ||
                      testSyntax.Contains(".bfc", StringComparison.InvariantCultureIgnoreCase)))
                {
                    "Target must be either .dll or .csproj or .bfc".LogDebug();
                    return Rxn.Empty <StartUnitTest>();
                }

                if (testSyntax.Contains(".bfc"))
                {
                    return GetTargetsFromBfc(testSyntax, parseTestSyntax, forParallelExection);
                }

                if (!testSyntax.Contains("*"))
                {
                    return GetTargetsFromDll(args, testSyntax, forCompete);
                }
                else
                {
                    return GetTargetsFromPath(args, testSyntax, forCompete);
                }
            })
                   .Select(e =>
            {
                e.Dll = e.Dll.AsCrossPlatformPath();

                if (!FocusedTest.IsNullOrWhitespace())
                {
                    e.RunThisTest = FocusedTest;
                }

                return e;
            }));
        }
Пример #15
0
        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)
                   );
        }
Пример #16
0
 public IObservable <CommandResult> Handle(StartUnitTest command)
 {
     Queue(command);
     //the result will be broadcast when the queue processes the command
     return(Rxn.Empty <CommandResult>());
 }
Пример #17
0
        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);
            }));
        }
Пример #18
0
        /// <summary>
        /// todo: fix issue with not broadcasting all test stats to appstatus, only first time
        /// </summary>
        /// <param name="testCluster"></param>
        /// <param name="unitTestToRun"></param>
        /// <param name="publusher"></param>
        /// <param name="reactorMgr"></param>
        private void BroadcasteStatsToTestArena(IManageReactors reactorMgr)
        {
            var bfgReactor = reactorMgr.GetOrCreate("bfg").Reactor;

            //need to fix health which will allow this to be viewed on the appstatus portal. should monitor health of fanout stratergy
            //
            //IMonitorActionFactory<IRxn> health =MonitorHealth
            RxnCreator.MonitorHealth <IRxn>(bfgReactor, "theBFG", out var _before, () => Rxn.Empty()).SelectMany(bfgReactor.Output).Until();


            $"Heartbeating".LogDebug();
            bfgReactor.Output.Publish(new PerformAPing()).Until();
        }
Пример #19
0
        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()));
        }
Пример #20
0
        public IObservable <Unit> RunTestSuiteInTestArena(StartUnitTest work, StreamWriter testLog, string logDir)
        {
            $"Preparing to run {(work.RunAllTest ? "All" : work.RunThisTest)} in {work.Dll}".LogDebug();

            if (!Directory.Exists(logDir))
            {
                Directory.CreateDirectory(logDir);
            }

            var keepTestUpdatedIfRequested =
                work.UseAppUpdate.ToObservable(); //if not using updates, the dest folder is our root

            if (!File.Exists(work.Dll))
            {
                if (work.UseAppUpdate.IsNullOrWhitespace())
                {
                    _rxnManager.Publish(new UnitTestResult()
                    {
                        WasSuccessful = false, Message = $"Cannot find target @{work.Dll}".LogDebug()
                    }.AsResultOf(work));
                    return(Rxn.Empty <Unit>());
                }

                keepTestUpdatedIfRequested = _updateService.KeepUpdated(work.UseAppUpdate, work.UseAppVersion, theBfg.GetTestSuiteDir(work.UseAppUpdate, work.UseAppVersion), new RxnAppCfg()
                {
                    AppStatusUrl = work.AppStatusUrl.IsNullOrWhiteSpace("http://localhost:888"),
                    SystemName   = work.UseAppUpdate,
                    KeepUpdated  = true
                }, true);
            }
            else
            {
                work.Dll = FindIfNotExists(work.Dll);
            }

            return(keepTestUpdatedIfRequested //run the test
                   .Select(testPath =>
            {
                $"Running {work.Dll}".LogDebug();

                foreach (var arena in _arena())
                {
                    try
                    {
                        var tests = arena.ListTests(work.Dll).WaitR();
                        if (tests.AnyItems())
                        {
                            return arena.Start(Name, work, testLog, logDir).SelectMany(_ => _rxnManager.Publish(_));
                        }
                    }
                    catch (Exception)
                    {
                        continue;
                    }
                }

                "Argh, couldnt find a test arena to run this test".LogDebug();
                _rxnManager.Publish(new UnitTestResult()
                {
                    WasSuccessful = false, Message = $"No test arena on host is compatible with {work.Dll}"
                }.AsResultOf(work));
                return Rxn.Empty <Unit>();
            })
                   .Switch());
        }
Пример #21
0
 public IObservable <CommandResult> Handle(StopRecording command)
 {
     return(Rxn.Create(() => _isStarted.OnNext(false)).ToObservable().Select(_ => CommandResult.Success($"Recording stopped").AsResultOf(command)));
 }
Пример #22
0
        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()
                ;
            }));
        }
Пример #23
0
        public IObservable <IRxn> Process(TestArenaCfgUpdated @event)
        {
            @event.Cfg?.Save();

            return(Rxn.Empty <IRxn>());
        }