Example #1
0
        public void PromptInteractive()
        {
            LoggedConsole.SuppressInteractive = false;
            using (var memoryStream = new MemoryStream())
            {
                var inWriter = new StreamWriter(memoryStream);
                using (var streamReader = new StreamReader(memoryStream))
                    using (var stringWriter = new StringWriter())
                    {
                        inWriter.AutoFlush = true;
                        Console.SetIn(streamReader);

                        Console.SetOut(stringWriter);

                        LoggedConsole.WriteLine("Test");

                        inWriter.WriteLine("anthony");
                        streamReader.BaseStream.Position = 0;
                        streamReader.BaseStream.Flush();

                        var task = Task.Run(() => LoggedConsole.Prompt("Enter your name:"));

                        Assert.IsTrue(task.Wait(TimeSpan.FromSeconds(10)));

                        var actual = stringWriter.ToString();
                        StringAssert.Contains(actual, "Enter your name:");
                        //StringAssert.Contains(actual, "anthony:");

                        Assert.AreEqual("anthony", task.Result);
                    }
            }
        }
Example #2
0
        public void PromptTimesOut()
        {
            LoggedConsole.SuppressInteractive = false;
            Assert.IsTrue(LoggedConsole.IsInteractive);

            using (var reader = new InfiniteTextStream(random: TestHelpers.Random.GetRandom()))
            {
                Console.SetIn(reader);

                Assert.ThrowsException <TimeoutException>(
                    () => LoggedConsole.Prompt("Enter your name:", timeout: TimeSpan.FromMilliseconds(500)),
                    "Timed out waiting for user input to prompt:");
            }
        }
Example #3
0
        public void PromptNonInteractive()
        {
            MainEntry.SetLogVerbosity(LogVerbosity.Info, false);
            using (var stringWriter = new StringWriter())
            {
                Console.SetOut(stringWriter);

                LoggedConsole.WriteLine("Test");
                LoggedConsole.SuppressInteractive = true;
                var result = LoggedConsole.Prompt("Enter your name:");

                var actual = stringWriter.ToString();
                StringAssert.Contains(actual, "User prompt \"Enter your name:\" suppressed because session is not interactive");

                Assert.AreEqual(null, result);
            }

            MainEntry.SetLogVerbosity(LogVerbosity.Warn, true);
        }
        public static async Task <int> ExecuteAsync(Arguments arguments)
        {
            Log.Info("Event statistics analysis begin");

            // validate arguments

            var input  = arguments.Source;
            var config = arguments.Config.ToFileInfo();

            if (!input.Exists)
            {
                throw new FileNotFoundException("Cannot find source file", input.FullName);
            }

            // try an automatically find the config file
            if (config == null)
            {
                throw new FileNotFoundException("No config file argument provided");
            }
            else if (!config.Exists)
            {
                Log.Warn($"Config file {config.FullName} not found... attempting to resolve config file");

                // we use  the original input string - Using FileInfo fullname always produces an
                // absolute path relative to pwd... we don't want to prematurely make assumptions:
                // e.g. We require a missing absolute path to fail... that wouldn't work with .Name
                // e.g. We require a relative path to try and resolve, using .FullName would fail the first absolute
                //    check inside ResolveConfigFile
                config = ConfigFile.Resolve(arguments.Config, Directory.GetCurrentDirectory().ToDirectoryInfo());
            }

            // if a temp dir is not given, use output dir as temp dir
            if (arguments.TempDir == null)
            {
                Log.Warn("No temporary directory provided, using backup directory");
            }

            // Remote: create an instance of our API helpers
            IApi api = arguments.WorkbenchApi.IsNullOrEmpty() ? Api.Default : Api.Parse(arguments.WorkbenchApi);

            // log some helpful messages
            Log.Info("Events file:         " + input);
            Log.Info("Configuration file:  " + config);
            Log.Info("Output folder:       " + arguments.Output);
            Log.Info("Temp File Directory: " + arguments.TempDir);
            Log.Info("Api:                 " + api);

            // Remote: Test we can log in to the workbench
            var auth = new AuthenticationService(api);
            Task <IAuthenticatedApi> task;

            if (arguments.AuthenticationToken.IsNotWhitespace())
            {
                Log.Debug("Using token for authentication");
                task = auth.CheckLogin(arguments.AuthenticationToken);
            }
            else
            {
                var username = LoggedConsole.Prompt("Enter your username or email for the acoustic workbench:");
                var password = LoggedConsole.Prompt("Enter your password for the acoustic workbench:", forPassword: true);
                task = auth.Login(username, password);

                //task = auth.Login("*****@*****.**", "tsettest");
            }

            LoggedConsole.WriteWaitingLine(task, "Logging into workbench...");

            var authenticatedApi = await task.TimeoutAfter(Service.ClientTimeout).ConfigureAwait(false);

            Log.Info("Login success" + authenticatedApi);

            // read events/annotation file
            Log.Info("Now reading input data");

            // Read events from provided CSV file.
            // Also tag them with an order index to allow sorting in the same order as they were provided to us.
            var events = Csv
                         .ReadFromCsv <ImportedEvent>(input, throwOnMissingField: false)
                         .Select(
                (x, i) =>
            {
                x.Order = i;
                return(x);
            })
                         .ToArray();

            if (events.Length == 0)
            {
                Log.Warn("No events imported - source file empty. Exiting");
                return(ExceptionLookup.NoData);
            }

            Log.Info($"Events read, {events.Length} read.");

            // need to validate the events
            var invalidEvents = events.Where(e => !e.IsValid()).ToArray();

            if (invalidEvents.Length > 0)
            {
                throw new InvalidOperationException(
                          "Invalid event detected."
                          + $" {invalidEvents.Length} events are not valid. The first invalid event is {invalidEvents[0]}");
            }

            // next gather meta data for all events
            // and transform list of events into list of segments
            // NOTE: to save on I/O sometimes if events share the same audio block, then multiple events will be
            // bundled into the same analysis segment.
            var resolver = new EventMetadataResolver(
                authenticatedApi,
                PaddingFunction,
                arguments.Parallel ? 25 : 1);
            var metadataTask = resolver.GetRemoteMetadata(events);

            // wait for 1 second per event - this should be an order of magnitude greater than what is needed
            ISegment <AudioRecording>[] segments = await metadataTask.TimeoutAfter(events.Length);

            Log.Info($"Metadata collected, preparing to start analysis");

            // finally time to start preparing jobs
            ISourcePreparer preparer = new RemoteSourcePreparer(authenticatedApi, allowSegmentcutting: false);

            AnalysisCoordinator coordinator = new AnalysisCoordinator(
                preparer,
                SaveBehavior.Never,
                uniqueDirectoryPerSegment: false,
                isParallel: arguments.Parallel);

            // instantiate the Analysis
            EventStatisticsAnalysis analysis = new EventStatisticsAnalysis();

            // derserialize the config file
            var configuration = analysis.ParseConfig(config);

            AnalysisSettings settings = analysis.DefaultSettings;

            settings.AnalysisOutputDirectory = arguments.Output;
            settings.AnalysisTempDirectory   = arguments.TempDir;
            settings.Configuration           = configuration;

            var results = coordinator.Run(segments, analysis, settings);

            var allEvents = results.SelectMany(es => es.Events).ToArray();

            var eventsWithErrors = allEvents.Count(x => ((EventStatistics)x).Error);

            if (eventsWithErrors > 0)
            {
                Log.Warn($"Errors occurred when calculating statistics for {eventsWithErrors} events.");
            }

            Log.Trace("Sorting event statistics results");
            Array.Sort(allEvents);

            Log.Info("Executing summary");

            // TODO: implement if needed
            analysis.SummariseResults(settings, null, allEvents, null, null, results);

            Log.Debug("Summary complete");

            var instanceOutputDirectory =
                AnalysisCoordinator.GetNamedDirectory(settings.AnalysisOutputDirectory, analysis);

            var resultName = FilenameHelpers.AnalysisResultPath(
                instanceOutputDirectory,
                input,
                analysis.Identifier,
                "csv");

            // NOTE: we are only saving event files
            Log.Info($"Writing results to {resultName}");
            analysis.WriteEventsFile(resultName.ToFileInfo(), allEvents.AsEnumerable());
            Log.Debug("Writing events completed");

            var summaryStats = new
            {
                numberEvents           = allEvents.Length,
                durationEvents         = allEvents.Sum(x => ((EventStatistics)x).EventDurationSeconds),
                numberRecordings       = allEvents.Select(x => ((EventStatistics)x).AudioRecordingId).Distinct().Count(),
                durationAudioProcessed = results.Sum(x => x.SegmentAudioDuration.TotalSeconds),
                remoteAudioDownloaded  = (preparer as RemoteSourcePreparer)?.TotalBytesRecieved,
            };

            Log.Info("Summary statistics:\n" + Json.SerializeToString(summaryStats));

            Log.Success("Event statistics analysis complete!");

            return(ExceptionLookup.Ok);
        }