//===============================================================================
// Microsoft patterns & practices Enterprise Library
// Logging Application Block
//===============================================================================
// Copyright © Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================

using System;
using System.Diagnostics;
using System.Management;
using System.Text;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.Tests
{
    [TestClass]
    public class WMIListenerFixture
    {
        bool wmiLogged;
        string wmiResult;
        string wmiPath = @"\root\EnterpriseLibrary";
        ManagementBaseObject wmiLogEntry;

        void BlockUntilWMIEventArrives()
        {
            // loop and poll the event watcher
            bool loop = true;
            int count = 0;
            int timeoutCount = 100;
            while (loop)
            {
                // keep looping until the event handler gets called or we reach our timeout
                loop = !wmiLogged && (count++ < timeoutCount);
                Thread.Sleep(100);
            }
        }

        void watcher_EventArrived(object sender,
                                  EventArrivedEventArgs args)
        {
            wmiLogged = true;
            wmiResult = args.NewEvent.GetText(TextFormat.Mof);
            wmiLogEntry = args.NewEvent;
        }

        void SendLogEntry(WmiTraceListener listener,
                          LogEntry logEntry)
        {
            ManagementScope scope = new ManagementScope(@"\\." + wmiPath);
            scope.Options.EnablePrivileges = true;

            StringBuilder sb = new StringBuilder("SELECT * FROM ");
            sb.Append("LogEntryV20");
            string query = sb.ToString();
            EventQuery eq = new EventQuery(query);

            using (ManagementEventWatcher watcher = new ManagementEventWatcher(scope, eq))
            {
                watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
                watcher.Start();

                LogSource source = new LogSource("notfromconfig", SourceLevels.All);
                source.Listeners.Add(listener);
                source.TraceData(TraceEventType.Error, 1, logEntry);

                BlockUntilWMIEventArrives();

                watcher.Stop();
            }
        }

        [TestInitialize]
        public void ResetLogEntryInfo()
        {
            wmiLogged = false;
            wmiResult = string.Empty;
            wmiPath = @"\root\EnterpriseLibrary";
            wmiLogEntry = null;
        }

        [TestMethod]
        public void TestWMIEventOccurred()
        {
            WmiTraceListener listener = new WmiTraceListener();

            LogEntry logEntry = new LogEntry("message", "cat1", 0, 0, TraceEventType.Error, "title", null);
            SendLogEntry(listener, logEntry);

            Assert.IsTrue(wmiLogged);
            Assert.IsTrue(wmiResult.IndexOf("message") > -1);
        }

        [TestMethod]
        public void TestWMIEventWasFiltered()
        {
            WmiTraceListener listener = new WmiTraceListener();
            listener.Filter = new EventTypeFilter(SourceLevels.Off);

            LogEntry logEntry = new LogEntry("message", "cat1", 0, 0, TraceEventType.Error, "title", null);
            SendLogEntry(listener, logEntry);

            Assert.IsFalse(wmiLogged);
            Assert.IsFalse(wmiResult.IndexOf("message") > -1);
        }

        [TestMethod]
        public void TestWMIEventFiredApplyingFilter()
        {
            WmiTraceListener listener = new WmiTraceListener();
            listener.Filter = new EventTypeFilter(SourceLevels.Warning);

            LogEntry logEntry = new LogEntry("message", "cat1", 0, 0, TraceEventType.Error, "title", null);
            SendLogEntry(listener, logEntry);

            Assert.IsTrue(wmiLogged);
            Assert.IsTrue(wmiResult.IndexOf("message") > -1);
        }

        [TestMethod]
        public void AttributeLookupWillNotHaveAnEffect()
        {
            WmiTraceListener listener = new WmiTraceListener();
            listener.Attributes.Add("formatter", "nonexistent");
        }

        [TestMethod]
        public void TestCanGetActivityIdStringWithWMI()
        {
            WmiTraceListener listener = new WmiTraceListener();

            LogEntry logEntry = new LogEntry("message", "cat1", 0, 0, TraceEventType.Error, "title", null);
            Guid logEntryGuid = Guid.NewGuid();
            logEntry.ActivityId = logEntryGuid;
            SendLogEntry(listener, logEntry);

            Assert.IsTrue(wmiLogged);
            Assert.AreEqual(wmiLogEntry.GetPropertyValue("ActivityIdString"), logEntryGuid.ToString());
        }

        [TestMethod]
        public void TestCanGetcategoriesStringsWithWMI()
        {
            WmiTraceListener listener = new WmiTraceListener();

            LogEntry logEntry = new LogEntry("message", new string[] { "cat1", "cat2", "cat3" }, 0, 0, TraceEventType.Error, "title", null);
            SendLogEntry(listener, logEntry);

            Assert.IsTrue(wmiLogged);
            string[] categoriesStrings = (string[])wmiLogEntry.GetPropertyValue("CategoriesStrings");
            Assert.AreEqual(categoriesStrings.Length, logEntry.Categories.Count);
        }

        [TestMethod]
        public void TestLoggingACustomLogEntry()
        {
            WmiTraceListener listener = new WmiTraceListener();

            MyCustomLogEntry logEntry = new MyCustomLogEntry();
            logEntry.MyName = "Enterprise Library Tester";
            SendLogEntry(listener, logEntry);

            Assert.IsTrue(wmiLogged);
            Assert.AreEqual(wmiLogEntry.GetPropertyValue("MyName"), logEntry.MyName);
        }
    }
}
