/// <summary>
 /// Initializes a new instance of the <see cref="PersistenceChannel"/> class.
 /// </summary>
 /// <param name="storageFolderName">
 /// A folder name. Under this folder all the transmissions will be saved. 
 /// Setting this value groups channels, even from different processes. 
 /// If 2 (or more) channels has the same <c>storageFolderName</c> only one channel will perform the sending even if the channel is in a different process/AppDomain/Thread.  
 /// </param>
 /// <param name="sendersCount">
 /// Defines the number of senders. A sender is a long-running thread that sends telemetry batches in intervals defined by <see cref="SendingInterval"/>. 
 /// So the amount of senders also defined the maximum amount of http channels opened at the same time.
 /// </param>        
 public PersistenceChannel(string storageFolderName, int sendersCount = 3)
 {   
     this.TelemetryBuffer = new TelemetryBuffer();
     this.storage = new Storage(storageFolderName);
     this.Transmitter = new PersistenceTransmitter(this.storage, sendersCount);
     this.flushManager = new FlushManager(this.storage, this.TelemetryBuffer);
     this.EndpointAddress = Constants.TelemetryServiceEndpoint;
     this.developerMode = false;
 }
        public void PeekedItemIsNOnlyotReturnedOnce()
        {
            // Setup - create a storage with one item
            Storage storage = new Storage("unittest" + Guid.NewGuid().ToString());
            Transmission transmissionToEnqueue = CreateTransmissionAndEnqueueIt(storage);

            // Act
            StorageTransmission firstPeekedTransmission = storage.Peek();
            StorageTransmission secondPeekedTransmission = storage.Peek();

            // Asserts            
            Assert.IsNotNull(firstPeekedTransmission);
            Assert.IsNull(secondPeekedTransmission);
        }
        public void EnqueuedContentIsEqualToPeekedContent()
        {
            // Setup
            Storage storage = new Storage("unittest" + Guid.NewGuid().ToString());
            Transmission transmissionToEnqueue = CreateTransmission(new TraceTelemetry("mock_item"));

            // Act
            storage.EnqueueAsync(transmissionToEnqueue).ConfigureAwait(false).GetAwaiter().GetResult();
            StorageTransmission peekedTransmission = storage.Peek();

            // Asserts
            string enqueuedContent = Encoding.UTF8.GetString(transmissionToEnqueue.Content, 0, transmissionToEnqueue.Content.Length);
            string peekedContent = Encoding.UTF8.GetString(peekedTransmission.Content, 0, peekedTransmission.Content.Length);
            Assert.AreEqual(peekedContent, enqueuedContent);
        }
        public void DeletedItemIsNotReturnedInCallsToPeek()
        {
            // Setup - create a storage with one item
            Storage storage = new Storage("unittest" + Guid.NewGuid().ToString());
            Transmission transmissionToEnqueue = CreateTransmissionAndEnqueueIt(storage);

            // Act
            StorageTransmission firstPeekedTransmission;

            // if item is not disposed,peek will not return it (regardless of the call to delete). 
            // So for this test to actually test something, using 'using' is required.  
            using (firstPeekedTransmission = storage.Peek())
            {
                storage.Delete(firstPeekedTransmission);
            }

            StorageTransmission secondPeekedTransmission = storage.Peek();

            // Asserts            
            Assert.IsNotNull(firstPeekedTransmission);
            Assert.IsNull(secondPeekedTransmission);
        }
        public void PeekedItemIsReturnedAgainAfterTheItemInTheFirstCallToPeekIsDisposed()
        {
            // Setup - create a storage with one item
            Storage storage = new Storage("unittest" + Guid.NewGuid().ToString());
            Transmission transmissionToEnqueue = CreateTransmission(new TraceTelemetry("mock_item"));
            storage.EnqueueAsync(transmissionToEnqueue).ConfigureAwait(false).GetAwaiter().GetResult();

            // Act
            StorageTransmission firstPeekedTransmission;
            using (firstPeekedTransmission = storage.Peek())
            {
            }

            StorageTransmission secondPeekedTransmission = storage.Peek();

            // Asserts            
            Assert.IsNotNull(firstPeekedTransmission);
            Assert.IsNotNull(secondPeekedTransmission);
        }
        private static Transmission CreateTransmissionAndEnqueueIt(Storage storage)
        {
            Transmission firstTransmission = CreateTransmission(new TraceTelemetry(Guid.NewGuid().ToString()));
            storage.EnqueueAsync(firstTransmission).ConfigureAwait(false).GetAwaiter().GetResult();

            return firstTransmission;
        }
        public void WhenStorageFolderIsNullPeekReturnsNothing()
        {
            // Setup - create a storage with 2 items
            Storage storage = new Storage("unittest" + Guid.NewGuid().ToString());
            storage.StorageFolderInitialized = true;

            // Act - Enqueue twice
            CreateTransmissionAndEnqueueIt(storage);

            // Asserts - Second Peek should be null             
            Assert.IsNull(storage.Peek());
        }
        public void WhenMaxSizeIsReachedThenEnqueuedTranmissionsAreDropped()
        {
            // Setup - create a storage with 2 items
            Storage storage = new Storage("unittest" + Guid.NewGuid().ToString());
            storage.CapacityInBytes = 200; // Each file enqueued in CreateTransmissionAndEnqueueIt is ~300 bytes.

            // Act - Enqueue twice
            CreateTransmissionAndEnqueueIt(storage);
            CreateTransmissionAndEnqueueIt(storage);

            // Asserts - Second Peek should be null 
            Assert.IsNotNull(storage.Peek());
            Assert.IsNull(storage.Peek());
        }
        public void WhenMaxFilesIsOneThenSecondTranmissionIsDropped()
        {
            // Setup
            Storage storage = new Storage("unittest" + Guid.NewGuid().ToString());
            storage.MaxFiles = 1;

            // Act - Enqueue twice
            CreateTransmissionAndEnqueueIt(storage);
            CreateTransmissionAndEnqueueIt(storage);

            // Asserts - Second Peek should be null 
            Assert.IsNotNull(storage.Peek());
            Assert.IsNull(storage.Peek());
        }
        public void WhenStorageHasTwoItemsThenTwoCallsToPeekReturns2DifferentItems()
        {
            // Setup - create a storage with 2 items
            Storage storage = new Storage("unittest" + Guid.NewGuid().ToString());
            Transmission firstTransmission = CreateTransmissionAndEnqueueIt(storage);
            Transmission secondTransmission = CreateTransmissionAndEnqueueIt(storage);

            // Act
            StorageTransmission firstPeekedTransmission = storage.Peek();
            StorageTransmission secondPeekedTransmission = storage.Peek();

            // Asserts            
            Assert.IsNotNull(firstPeekedTransmission);
            Assert.IsNotNull(secondPeekedTransmission);

            string first = Encoding.UTF8.GetString(firstPeekedTransmission.Content, 0, firstPeekedTransmission.Content.Length);
            string second = Encoding.UTF8.GetString(secondPeekedTransmission.Content, 0, secondPeekedTransmission.Content.Length);
            Assert.AreNotEqual(first, second);
        }