public void SamplerInvokesTransformerTransformMethod()
        {
            var collectedSamples = new List <Dictionary <GCSampleType, float> >();

            var mockListener = Mock.Create <ISampledEventListener <Dictionary <GCSampleType, float> > >();

            Mock.Arrange(() => mockListener.Sample())
            .Returns(() => new Dictionary <GCSampleType, float>());

            Func <ISampledEventListener <Dictionary <GCSampleType, float> > > mockListenerFactory = () =>
            {
                return(mockListener);
            };

            var mockTransfomer = Mock.Create <IGcSampleTransformer>();

            Mock.Arrange(() => mockTransfomer.Transform(Arg.IsAny <Dictionary <GCSampleType, float> >()))
            .DoInstead <Dictionary <GCSampleType, float> >((sampleValues) => { collectedSamples.Add(sampleValues); });

            var sampler = new GCSamplerNetCore(_mockScheduler, mockListenerFactory, mockTransfomer, _fxSamplerValidForFrameworkOverride);

            sampler.Start();
            sampler.Sample();

            Assert.AreEqual(1, collectedSamples.Count, $"Transform should have only been called once, it was called {collectedSamples.Count} time(s).");
        }
        public void SamplerTransformsValuesFromExpectedGCSampleTypes()
        {
            var collectedSamples = new List <Dictionary <GCSampleType, float> >();

            var mockListener = Mock.Create <ISampledEventListener <Dictionary <GCSampleType, float> > >();

            Mock.Arrange(() => mockListener.Sample())
            .Returns(() => ExpectedSampleTypes.ToDictionary(x => x, x => 0f));

            Func <ISampledEventListener <Dictionary <GCSampleType, float> > > mockListenerFactory = () =>
            {
                return(mockListener);
            };

            var mockTransfomer = Mock.Create <IGcSampleTransformer>();

            Mock.Arrange(() => mockTransfomer.Transform(Arg.IsAny <Dictionary <GCSampleType, float> >()))
            .DoInstead <Dictionary <GCSampleType, float> >((sampleValues) => { collectedSamples.Add(sampleValues); });

            var sampler = new GCSamplerNetCore(_mockScheduler, mockListenerFactory, mockTransfomer, _fxSamplerValidForFrameworkOverride);

            sampler.Start();
            sampler.Sample();

            Assert.AreEqual(1, collectedSamples.Count, "Only one sample should have been taken");
            Assert.That(collectedSamples[0].Keys.ToArray(), Is.EquivalentTo(ExpectedSampleTypes), $"Mismatch between the GSampleTypes returned from Sample to the expectedList");
        }
        public void SamplerDisposesEventListenerOnException()
        {
            var samplerWasStopped   = false;
            var listenerWasDisposed = false;

            var mockListener = Mock.Create <ISampledEventListener <Dictionary <GCSampleType, float> > >();

            Mock.Arrange(() => mockListener.Dispose())
            .DoInstead(() => { listenerWasDisposed = true; });

            //This is our mechanism for shutting down the sampler.  If a config change is used, it starts/stops 3x which makes
            //it difficult to determine current state.  Instead, throw an exception in the eventListener's sample method.
            Mock.Arrange(() => mockListener.Sample())
            .DoInstead(() => throw new Exception());

            Func <ISampledEventListener <Dictionary <GCSampleType, float> > > mockListenerFactory = () =>
            {
                return(mockListener);
            };

            var mockScheduler = Mock.Create <IScheduler>();

            //Prevents the scheduler from actually running
            Mock.Arrange(() => _mockScheduler.ExecuteEvery(Arg.IsAny <Action>(), Arg.IsAny <TimeSpan>(), Arg.IsAny <TimeSpan?>()))
            .DoNothing();

            //Tracks the stop executing for the scheduler which indicates that the sampler
            //has requested it to stop;
            Mock.Arrange(() => mockScheduler.StopExecuting(Arg.IsAny <Action>(), Arg.IsAny <TimeSpan?>()))
            .DoInstead <Action, TimeSpan?>((a, t) => { samplerWasStopped = true; });

            var sampler = new GCSamplerNetCore(mockScheduler, mockListenerFactory, _mockTransformer, _fxSamplerValidForFrameworkOverride);

            //Act
            sampler.Start();

            //Cause error which will shut down the sampler
            sampler.Sample();

            //Assert
            Assert.IsTrue(samplerWasStopped);
            Assert.IsTrue(listenerWasDisposed);
        }
        public void FailureToCollectSampleShutsDownSampler()
        {
            var samplerWasStopped = false;
            var sampleAttempted   = false;

            var mockListener = Mock.Create <ISampledEventListener <Dictionary <GCSampleType, float> > >();

            Mock.Arrange(() => mockListener.Sample())
            .DoInstead(() =>
            {
                sampleAttempted = true;
                throw new Exception();
            });

            Func <ISampledEventListener <Dictionary <GCSampleType, float> > > mockListenerFactory = () =>
            {
                return(mockListener);
            };


            var mockScheduler = Mock.Create <IScheduler>();

            //Prevents the scheduler from actually running
            Mock.Arrange(() => _mockScheduler.ExecuteEvery(Arg.IsAny <Action>(), Arg.IsAny <TimeSpan>(), Arg.IsAny <TimeSpan?>()))
            .DoNothing();

            //Tracks the stop executing for the scheduler which indicates that the sampler
            //has requested it to stop;
            Mock.Arrange(() => mockScheduler.StopExecuting(Arg.IsAny <Action>(), Arg.IsAny <TimeSpan?>()))
            .DoInstead <Action, TimeSpan?>((a, t) => { samplerWasStopped = true; });



            //Act
            var sampler = new GCSamplerNetCore(mockScheduler, mockListenerFactory, _mockTransformer, _fxSamplerValidForFrameworkOverride);

            sampler.Start();
            sampler.Sample();

            Assert.IsTrue(sampleAttempted);
            Assert.IsTrue(samplerWasStopped);
        }