using System.Collections.Generic; using NUnit.Framework; namespace System.ComponentModel.Design { /// /// A set of reusable tests for testing types that implement /// . /// public abstract class ServiceContainerTests : ServiceProviderTests { [Test, Description("A test that ensures the " + "IServiceContainer.AddService(Type, Object) method sets the service " + "properly.")] public void AddServiceTypeObjectTest() { IServiceContainer serviceContainer = CreateServiceContainer(); ICollection collection = new List(); Type collectionType = typeof(ICollection); serviceContainer.AddService(collectionType, collection); object collectionService = serviceContainer.GetService(collectionType); Assert.AreEqual(collection, collectionService, "Unexpected service " + "was retrieved."); } [Test, Description("A test that ensures the " + "IServiceContainer.AddService(Type, Object, Boolean) method sets " + "the service properly and does so on the parents if told to do so.")] public void AddServiceTypeObjectBoolTest() { ICollection service = new List(); Type serviceType = typeof(ICollection); // Check the promotion of a service { IServiceContainer serviceContainer = CreateServiceContainer(); serviceContainer.AddService(serviceType, service, true); CheckServicesInHierarchy(serviceContainer, serviceType, service); } // Check the lack of promotion of a service { IServiceContainer serviceContainer = CreateServiceContainer(); serviceContainer.AddService(serviceType, service, false); CheckServicesInHierarchy(serviceContainer, serviceType, null); } } [Test, Description("A test that ensures the " + "IServiceContainer.AddService(Type, ServiceCreatorCallback) method " + "sets the service properly.")] public void AddServiceTypeServiceCreatorCallbackTest() { IServiceContainer serviceContainer = CreateServiceContainer(); ServiceCreatorCallbackTester tester = new ServiceCreatorCallbackTester(); Type collectionType = typeof(ICollection); serviceContainer.AddService(collectionType, tester.Callback); Assert.AreEqual(false, tester.Invoked, "The ServiceCreatorCallback should " + "not have been invoked."); object collectionService = serviceContainer.GetService(collectionType); Assert.AreEqual(true, tester.Invoked, "The ServiceCreatorCallback should " + "have been invoked."); Assert.AreEqual(tester.Service, collectionService, "Unexpected service " + "was retrieved."); } /// /// A helper class for use in the /// method. This /// class stores the being injected as well as the /// property which indicates whether the callback /// method was invoked or not. /// class ServiceCreatorCallbackTester { public ServiceCreatorCallbackTester() { Invoked = false; Service = new List(); } public object Callback(IServiceContainer servCont, Type type) { Invoked = true; return Service; } public bool Invoked { get; private set; } public ICollection Service { get; private set; } } [Test, Description("A test that ensures the " + "IServiceContainer.AddService(Type, ServiceCreatorCallback, Boolean) " + "method sets the service properly and does so on the parents if told " + "to do so.")] public void AddServiceTypeServiceCreatorCallbackBooleanTest() { ICollection service = new List(); Type serviceType = typeof(ICollection); // Check the promotion of a service { IServiceContainer serviceContainer = CreateServiceContainer(); serviceContainer.AddService(serviceType, (servCont, type) => service, true); CheckServicesInHierarchy(serviceContainer, serviceType, service); } // Check the lack of promotion of a service { IServiceContainer serviceContainer = CreateServiceContainer(); serviceContainer.AddService(serviceType, (servCont, type) => service, false); CheckServicesInHierarchy(serviceContainer, serviceType, null); } } [Test, Description("A test that ensures IServiceContainer.Remove(Type) " + "properly removes a service from the IServicesContainer container.")] public void RemoveServiceTypeTest() { IServiceContainer serviceContainer = CreateServiceContainer(); ICollection collection = new List(); Type serviceType = typeof(ICollection); serviceContainer.AddService(serviceType, collection); RemoveServiceCheck(serviceContainer, collection, serviceType, (servCont, type) => serviceContainer.RemoveService(type)); } [Test, Description("A test that ensures " + "IServiceContainer.Remove(Type, Boolean) properly removes a service " + "from the IServicesContainer container and propagates the change to " + "the parent IServiceContainer.")] public void RemoveServiceTypeBooleanTest() { ICollection collection = new List(); Type serviceType = typeof(ICollection); // Check the promotion of service removal. { IServiceContainer serviceContainer = CreateServiceContainer(); serviceContainer.AddService(serviceType, collection, true); RemoveServiceCheck(serviceContainer, collection, serviceType, (servCont, type) => serviceContainer.RemoveService(type, true)); CheckServicesInHierarchy(serviceContainer, serviceType, null); } // Check the lack of promotion of a service removal. { IServiceContainer serviceContainer = CreateServiceContainer(); serviceContainer.AddService(serviceType, collection, true); RemoveServiceCheck(serviceContainer, collection, serviceType, (servCont, type) => serviceContainer.RemoveService(type, false)); CheckServicesInHierarchy(serviceContainer, serviceType, collection); } } [Test, Description("A test that ensures IServiceContainers can properly " + "override properly added services.")] public void OverrideServiceTest() { IServiceContainer serviceContainer = CreateServiceContainer(); Type serviceType = typeof (ICollection); ICollection service1 = new List(); ICollection service2 = new List(); // Add the service and ensure we can retrieve it as expected. { serviceContainer.AddService(serviceType, service1); object service = serviceContainer.GetService(serviceType); Assert.AreEqual(service1, service); } // Now override the service we just added and ensure we can retrieve // it as expected. { serviceContainer.AddService(serviceType, service2); object service = serviceContainer.GetService(serviceType); Assert.AreEqual(service2, service); } } /// /// Creates the to test. This method /// should always create a new instance. The /// must contain a service of type that /// is not null and equal to . /// The must also have the number of /// ancestors specified by . /// /// The instance to test. protected abstract IServiceContainer CreateServiceContainer(); /// /// Retrieves the parent of the /// passed in. /// /// The /// whose parent is to be retrieved. /// The parent of the /// instance or null if they instance has no parent. protected abstract IServiceContainer GetParent(IServiceContainer serviceContainer); protected override IServiceProvider CreateServiceProvider() { return CreateServiceContainer(); } /// /// The number of ancestors the returned /// by is expected to have. The /// value of this field is 2. /// protected const int ExpectedServiceAncestorCount = 2; /// /// Ensures the and its ancestors /// can handle the promotion of services, or lack thereof. /// /// The service container whose /// ancestors are to be checked to see if they contain the /// . /// The type of the service to check for in /// the . /// The service that is expected in the /// . void CheckServicesInHierarchy(IServiceContainer serviceContainer, Type serviceType, object expectedService) { serviceContainer = GetParent(serviceContainer); // Check the ancestors of the serviceContainer to see if the service // was added to them. While we are doing that, we'll keep a count to // ensure the IServiceContainer has the proper number of ancestors. int serviceContainerCount = 0; do { ++serviceContainerCount; object actualService = serviceContainer.GetService(serviceType); Assert.AreEqual(expectedService, actualService, "Unexpected service " + "was retrieved."); serviceContainer = GetParent(serviceContainer); } while (serviceContainer != null); Assert.AreEqual(ExpectedServiceAncestorCount, serviceContainerCount); } /// /// Tests an to see if it can handle /// the removal of a service. /// /// The /// to test. /// The service that is to be removed /// from the . Before the service is /// removed, the is checked to see /// if it exists. /// The of the service to /// remove. /// The method to be invoked that will /// remove the service of from the /// specified. static void RemoveServiceCheck(IServiceContainer serviceContainer, object serviceToBeRemoved, Type serviceType, Action removeService) { object collectionService = serviceContainer.GetService(serviceType); Assert.AreEqual(serviceToBeRemoved, collectionService, "Unexpected service " + "was retrieved."); removeService(serviceContainer, serviceType); collectionService = serviceContainer.GetService(serviceType); Assert.AreEqual(null, collectionService, "Service should have been " + "null"); } } }