Esempio n. 1
0
        public void AllDatabaseEntitiesHaveTypedIRepository()
        {
            SetupMEF();

            List <string> problems = new List <string>();

            foreach (var type in MEF.GetAllTypes().Where(t => typeof(DatabaseEntity).IsAssignableFrom(t)))
            {
                foreach (var constructorInfo in type.GetConstructors())
                {
                    var parameters = constructorInfo.GetParameters();

                    if (parameters.Any(p => p.ParameterType == typeof(IRepository)))
                    {
                        problems.Add($"Constructor found on Type {type} that takes {nameof(IRepository)}, it should take either {nameof(IDataExportRepository)} or {nameof(ICatalogueRepository)}");
                    }
                }
            }

            foreach (var problem in problems)
            {
                TestContext.Out.WriteLine(problem);
            }

            Assert.IsEmpty(problems);
        }
        private void Initialize()
        {
            initialized = true;

            //get all the SecondaryConstraints
            foreach (Type constraintType in _mef.GetAllTypes().Where(c => typeof(ISecondaryConstraint).IsAssignableFrom(c)))
            {
                //get all properties and fields which map to a database object
                var props  = constraintType.GetProperties().Where(p => typeof(IMapsDirectlyToDatabaseTable).IsAssignableFrom(p.PropertyType)).ToList();
                var fields = constraintType.GetFields().Where(f => typeof(IMapsDirectlyToDatabaseTable).IsAssignableFrom(f.FieldType)).ToList();

                //there are no suspect fields that could have hidden dependencies
                if (!props.Any() && !fields.Any())
                {
                    continue;
                }

                string constraintName = constraintType.Name;
                string pattern        = Regex.Escape("<SecondaryConstraint xsi:type=\"" + constraintName + "\">");

                //anything
                pattern += ".*";

                //this will be replaced by the ID of the thing we are deleting (dont match 1 to 115 though!)
                pattern += @"\b{0}\b";

                //then more of anything
                pattern += ".*";

                //then the end of the secondary constraint
                pattern += Regex.Escape("</SecondaryConstraint>");

                TheUsualSuspects.Add(new Suspect(pattern, constraintType, props, fields));
            }
        }
Esempio n. 3
0
        private IEnumerable <string> EnforceTypeBelongsInNamespace(Type InterfaceType, params string[] legalNamespaces)
        {
            SetupMEF();
            foreach (Type type in MEF.GetAllTypes().Where(InterfaceType.IsAssignableFrom))
            {
                if (type.Namespace == null)
                {
                    continue;
                }

                //don't validate classes in testing code
                if (type.Namespace.Contains(".Tests"))
                {
                    continue;
                }

                //theese guys can be wherever they want
                if (_exemptNamespaces.Any(e => type.Namespace.Contains(e)))
                {
                    continue;
                }

                if (!legalNamespaces.Any(ns => type.Namespace.Contains(ns)))
                {
                    yield return("Expected Type '" + type.Name + "' to be in namespace(s) '" + string.Join("' or '", legalNamespaces) + "' but it was in '" + type.Namespace + "'");
                }

                evaluatedClasses++;
            }

            Console.WriteLine("Evaluated " + evaluatedClasses + " classes for namespace compatibility");
        }
Esempio n. 4
0
        /// <summary>
        /// Lists assembly load errors and attempts to construct instances of all Types declared as Exports (which are ICheckable)
        /// </summary>
        /// <param name="notifier"></param>
        public void Check(ICheckNotifier notifier)
        {
            foreach (KeyValuePair <string, Exception> badAssembly in _mefPlugins.ListBadAssemblies())
            {
                notifier.OnCheckPerformed(new CheckEventArgs("Could not load assembly " + badAssembly.Key, CheckResult.Fail, badAssembly.Value));
            }

            foreach (Type t in _mefPlugins.GetAllTypes())
            {
                notifier.OnCheckPerformed(new CheckEventArgs("Found Type " + t, CheckResult.Success, null));

                if (typeof(ICheckable).IsAssignableFrom(t))
                {
                    try
                    {
                        _mefPlugins.CreateA <ICheckable>(t.FullName);
                    }
                    catch (Exception ex)
                    {
                        notifier.OnCheckPerformed(new CheckEventArgs(
                                                      "Class " + t.FullName +
                                                      " implements ICheckable but could not be created as an ICheckable.",
                                                      CheckResult.Warning, ex));
                    }
                }
            }
        }
Esempio n. 5
0
        public void FindProblems(MEF mef)
        {
            List <string> excusables = new List <string>()
            {
                "IPlugin",
                "IDataAccessCredentials",
                "IProcessTask" //this is inherited by IRuntimeTask too which isn't an IMapsDirectlyToDatabaseTable
            };
            List <string> problems = new List <string>();

            foreach (var dbEntities in mef.GetAllTypes().Where(t => typeof(DatabaseEntity).IsAssignableFrom(t)))
            {
                var matchingInterface = typeof(Catalogue).Assembly.GetTypes().SingleOrDefault(t => t.Name.Equals("I" + dbEntities.Name));

                if (matchingInterface != null)
                {
                    if (excusables.Contains(matchingInterface.Name))
                    {
                        continue;
                    }

                    if (!typeof(IMapsDirectlyToDatabaseTable).IsAssignableFrom(matchingInterface))
                    {
                        problems.Add("FAIL: Interface '" + matchingInterface.Name + "' does not inherit IMapsDirectlyToDatabaseTable");
                    }
                }
            }

            foreach (string problem in problems)
            {
                Console.WriteLine(problem);
            }

            Assert.AreEqual(0, problems.Count);
        }
Esempio n. 6
0
        public void GetRepositoryConstructor_AllDatabaseEntities_OneWinningConstructor()
        {
            SetupMEF();

            int countCompatible = 0;

            var badTypes = new Dictionary <Type, Exception>();

            foreach (Type t in MEF.GetAllTypes().Where(typeof(DatabaseEntity).IsAssignableFrom))
            {
                try
                {
                    var oc = new ObjectConstructor();
                    Assert.IsNotNull(oc.GetRepositoryConstructor(typeof(Catalogue)));
                    countCompatible++;
                }
                catch (Exception e)
                {
                    badTypes.Add(t, e);
                }
            }

            Assert.IsEmpty(badTypes);
            Assert.GreaterOrEqual(countCompatible, 10);
            Console.WriteLine("Found compatible constructors on " + countCompatible + " objects");
        }
Esempio n. 7
0
        public void Check(ICheckNotifier notifier)
        {
            foreach (Type t in _mef.GetAllTypes().Where(t => typeof(DatabaseEntity).IsAssignableFrom(t)))
            {
                if (typeof(IMapsDirectlyToDatabaseTable).IsAssignableFrom(t))
                {
                    if (t.IsInterface || t.IsAbstract || t.Name.StartsWith("Spontaneous"))
                    {
                        continue;
                    }
                    try
                    {
                        //spontaneous objects don't exist in the database.
                        if (typeof(SpontaneousObject).IsAssignableFrom(t))
                        {
                            continue;
                        }
                    }
                    catch (Exception)
                    {
                        continue;
                    }

                    notifier.OnCheckPerformed(new CheckEventArgs("Found type " + t, CheckResult.Success));

                    var docs = _commentStore.GetTypeDocumentationIfExists(t, true, true);

                    if (docs == null)
                    {
                        notifier.OnCheckPerformed(
                            new CheckEventArgs("Failed to get definition for class " + t.FullName, CheckResult.Fail));
                    }
                    else
                    {
                        Summaries.Add(t, docs);
                    }
                }
            }
        }
        public void FindProblems(List <string> csFilesList, MEF mef)
        {
            _csFilesList = csFilesList;

            //All node classes should have equality compare members so that tree expansion works properly
            foreach (Type nodeClass in mef.GetAllTypes().Where(t => typeof(Node).IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface))
            {
                if (nodeClass.Namespace == null || nodeClass.Namespace.StartsWith("System"))
                {
                    continue;
                }

                //class is excused
                if (excusedNodeClasses.Contains(nodeClass))
                {
                    continue;
                }

                //it's something like ProposeExecutionWhenTargetIsIDirectoryNode.cs i.e. it's not a Node!
                if (typeof(ICommandExecutionProposal).IsAssignableFrom(nodeClass))
                {
                    continue;
                }

                //if it's an ObjectUsedByOtherObjectNode then it will already have GetHashCode implemented
                if (typeof(IObjectUsedByOtherObjectNode).IsAssignableFrom(nodeClass))
                {
                    continue;
                }

                if (typeof(ExtractionArbitraryFolderNode).IsAssignableFrom(nodeClass))
                {
                    continue;
                }

                //these are all supported at base class level
                if (typeof(SingletonNode).IsAssignableFrom(nodeClass))
                {
                    if (!nodeClass.Name.StartsWith("All"))
                    {
                        problems.Add("Class '" + nodeClass.Name + "' is a SingletonNode but it's name doesn't start with All");
                    }

                    continue;
                }

                ConfirmFileHasText(nodeClass, "public override int GetHashCode()");
            }

            //All Menus should correspond to a data class
            foreach (Type menuClass in mef.GetAllTypes().Where(t => typeof(RDMPContextMenuStrip).IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface))
            {
                if (menuClass == typeof(RDMPContextMenuStrip)) //the basic class from which all are inherited
                {
                    continue;
                }

                //We are looking at something like AutomationServerSlotsMenu
                if (!menuClass.Name.EndsWith("Menu"))
                {
                    problems.Add("Class '" + menuClass + "' is a RDMPContextMenuStrip but it's name doesn't end with Menu");
                    continue;
                }

                foreach (ConstructorInfo c in menuClass.GetConstructors())
                {
                    if (c.GetParameters().Count() != 2)
                    {
                        problems.Add("Constructor of class '" + menuClass + "' which is an RDMPContextMenuStrip contained " + c.GetParameters().Count() + " constructor arguments.  These menus are driven by reflection (See RDMPCollectionCommonFunctionality.GetMenuWithCompatibleConstructorIfExists )");
                    }
                }


                var toLookFor         = menuClass.Name.Substring(0, menuClass.Name.Length - "Menu".Length);
                var expectedClassName = GetExpectedClassOrInterface(toLookFor);

                if (expectedClassName == null)
                {
                    problems.Add("Found menu called '" + menuClass.Name + "' but couldn't find a corresponding data class called '" + toLookFor + ".cs'");
                    continue;
                }

                ConfirmFileHasText(menuClass, "AddCommonMenuItems()", false);

                //expect something like this
                //public AutomationServerSlotsMenu(IActivateItems activator, AllAutomationServerSlotsNode databaseEntity)
                string expectedConstructorSignature = menuClass.Name + "(RDMPContextMenuStripArgs args," + expectedClassName;
                ConfirmFileHasText(menuClass, expectedConstructorSignature);

                FieldInfo[] fields = menuClass.GetFields(
                    BindingFlags.NonPublic |
                    BindingFlags.Instance);

                //find private fields declared at the object level (i.e. not in base class that are of type IActivateItem)
                var activatorField = fields.FirstOrDefault(f => f.DeclaringType == menuClass && f.FieldType == typeof(IActivateItems));
                if (activatorField != null)
                {
                    problems.Add("Menu '" + menuClass + "' contains a private field called '" + activatorField.Name + "'.  You should instead use base class protected field RDMPContextMenuStrip._activator");
                }
            }

            //Drag and drop / Activation - Execution Proposal system
            foreach (Type proposalClass in mef.GetAllTypes().Where(t => typeof(ICommandExecutionProposal).IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface))
            {
                if (proposalClass.Namespace.Contains("Rdmp.UI.Tests.DesignPatternTests"))
                {
                    continue;
                }

                //We are looking at something like AutomationServerSlotsMenu
                if (!proposalClass.Name.StartsWith("ProposeExecutionWhenTargetIs"))
                {
                    problems.Add("Class '" + proposalClass + "' is a ICommandExecutionProposal but it's name doesn't start with ProposeExecutionWhenTargetIs");
                    continue;
                }

                var    toLookFor         = proposalClass.Name.Substring("ProposeExecutionWhenTargetIs".Length);
                string expectedClassName = GetExpectedClassOrInterface(toLookFor);

                if (expectedClassName == null)
                {
                    problems.Add("Found proposal called '" + proposalClass + "' but couldn't find a corresponding data class called '" + toLookFor + ".cs'");
                }
            }

            //Make sure all user interface classes have the suffix UI
            foreach (Type uiType in mef.GetAllTypes().Where(t =>
                                                            (typeof(RDMPUserControl).IsAssignableFrom(t) || (typeof(RDMPForm).IsAssignableFrom(t)) &&
                                                             !t.IsAbstract && !t.IsInterface)))
            {
                if (!uiType.Name.EndsWith("UI") && !uiType.Name.EndsWith("_Design"))
                {
                    if (excusedUIClasses.Contains(uiType))
                    {
                        continue;
                    }

                    //also allow Screen1, Screen2 etc
                    if (Regex.IsMatch(uiType.Name, @"Screen\d") && uiType.IsNotPublic)
                    {
                        continue;
                    }

                    problems.Add("Class " + uiType.Name + " does not end with UI");
                }
            }


            foreach (string problem in problems)
            {
                Console.WriteLine("FATAL ERROR PROBLEM:" + problem);
            }

            Assert.AreEqual(problems.Count, 0);
        }
        private void AnalyseRelationshipPropertyUsages()
        {
            foreach (var t in mef.GetAllTypes())
            {
                if (!t.IsClass)
                {
                    continue;
                }

                //don't worry about the ToString method on classes that are IInjectKnown
                var toStringMethod = t.GetMethod("ToString", new Type[0]);

                //it doesn't have any ToString methods!
                if (toStringMethod == null)
                {
                    continue;
                }

                if (toStringMethod.DeclaringType == typeof(System.Object))
                {
                    continue;
                }

                if (toStringMethod.DeclaringType == typeof(MarshalByRefObject))
                {
                    continue;
                }

                /*
                 * IList<Instruction> instructions = null;
                 * try
                 * {
                 *  instructions = toStringMethod.GetInstructions();
                 * }
                 * catch (Exception e)
                 * {
                 *  Console.WriteLine(e);
                 * }
                 *
                 * if (instructions != null)
                 *  foreach (Instruction instruction in instructions)
                 *  {
                 *      MethodInfo methodInfo = instruction.Operand as MethodInfo;
                 *
                 *      if (methodInfo != null)
                 *      {
                 *          //is it a call to property
                 *          PropertyInfo prop;
                 *
                 *          if (RelationshipPropertyInfos.TryGetBySecond(methodInfo, out prop))
                 *          {
                 *
                 *              //It doesn't look injected but it is
                 *              if(t == typeof(JoinInfo))
                 *                  continue;
                 *
                 *              //if we are injectable for it
                 *      if( t.GetInterfaces().Any(x =>
                 *            x.IsGenericType &&
                 *            x.GetGenericTypeDefinition() == typeof(IInjectKnown<>) &&
                 *            x.GetGenericArguments()[0] == prop.PropertyType))
                 *          continue;
                 *
                 *              _fails.Add("FAIL: ToString method in Type " + t.FullName + " uses Relationship PropertyInfo " + prop.Name);
                 *          }
                 *      }
                 *  }*/
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Looks for the class name within the defined Types in all assemblies loaded in MEF.  If you pass an ICheckNotifier which responds to ProposedFixes and the class
        /// is found under a different namespace (e.g. due to the coder of the plugin refactoring the class to a new location in his assembly) then the callback
        /// userAcceptedSubstitution will be invoked.  Use AcceptAllCheckNotifier if you want the callback to always be called.
        /// </summary>
        /// <param name="notifier"></param>
        public void Check(ICheckNotifier notifier)
        {
            if (string.IsNullOrWhiteSpace(_classToFind))
            {
                notifier.OnCheckPerformed(new CheckEventArgs(
                                              "MEFChecker was asked to check for the existence of an Export class but the _classToFind string was empty",
                                              CheckResult.Fail, null));
                return;
            }

            string typeNameOnly = _classToFind.Substring(_classToFind.LastIndexOf(".") + 1);

            var allTypes = _mefPlugins.GetAllTypes().ToArray();

            if (allTypes.Any(t => t.FullName.Equals(_classToFind)))
            {
                notifier.OnCheckPerformed(new CheckEventArgs(
                                              "Found MEF class " + _classToFind + "",
                                              CheckResult.Success, null));
            }
            else
            {
                Type[] substitute = allTypes.Where(t => t.Name.Equals(typeNameOnly)).ToArray();

                if (substitute.Length == 0)
                {
                    notifier.OnCheckPerformed(new CheckEventArgs(
                                                  "Could not find MEF class called " + _classToFind + " in LoadModuleAssembly.GetAllTypes() and couldn't even find any with the same basic name (Note that we only checked Exported MEF types e.g. classes implementing IPluginAttacher, IPluginDataProvider etc)",
                                                  CheckResult.Fail, null));

                    Dictionary <string, Exception> badAssemblies = _mefPlugins.ListBadAssemblies();

                    if (badAssemblies.Any())
                    {
                        notifier.OnCheckPerformed(new CheckEventArgs(
                                                      "It is possible that the class you are looking for is in the BadAssemblies list",
                                                      CheckResult.Fail, null));
                    }
                    foreach (KeyValuePair <string, Exception> badAssembly in badAssemblies)
                    {
                        notifier.OnCheckPerformed(new CheckEventArgs("Bad Assembly " + badAssembly.Key, CheckResult.Warning,
                                                                     badAssembly.Value));
                    }
                }
                else if (substitute.Length == 1)
                {
                    bool acceptSubstitution = notifier.OnCheckPerformed(new CheckEventArgs(
                                                                            "Could not find MEF class called " + _classToFind + " but did find one called " +
                                                                            substitute[0].FullName,
                                                                            CheckResult.Fail, null,
                                                                            "Change reference to " + _classToFind + " to point to MEF assembly type " +
                                                                            substitute[0].FullName));

                    if (acceptSubstitution)
                    {
                        _userAcceptedSubstitution(substitute[0].FullName);
                    }
                }
                else
                {
                    notifier.OnCheckPerformed(new CheckEventArgs(
                                                  "Could not find MEF class called " + _classToFind +
                                                  ", we were looking for a suitable replacment (a Type with the same basic name) but we found " +
                                                  substitute.Length + " subistutitions!!! (" +
                                                  substitute.Aggregate("", (s, n) => s + n.FullName + ","), CheckResult.Fail, null));
                }
            }
        }
Esempio n. 11
0
        public void TestAllSupported()
        {
            //load all DatabaseEntity types
            MEF mef = new MEF();

            mef.Setup(new SafeDirectoryCatalog(TestContext.CurrentContext.TestDirectory));

            var types = mef.GetAllTypes()
                        .Where(t => typeof(DatabaseEntity).IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface).ToArray();

            var methods = typeof(UnitTests).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);
            var method  = methods.Single(m => m.Name.Equals("WhenIHaveA") && !m.GetParameters().Any());

            List <Type> notSupported = new List <Type>();

            foreach (Type t in types)
            {
                //ignore these types too
                if (SkipTheseTypes.Contains(t.Name) || t.Name.StartsWith("Spontaneous") || typeof(SpontaneousObject).IsAssignableFrom(t))
                {
                    continue;
                }

                DatabaseEntity instance = null;

                try
                {
                    //ensure that the method supports the Type
                    var generic = method.MakeGenericMethod(t);
                    instance = (DatabaseEntity)generic.Invoke(this, null);
                }
                catch (TargetInvocationException exception)
                {
                    if (exception.InnerException is TestCaseNotWrittenYetException)
                    {
                        notSupported.Add(t);
                    }
                    else
                    {
                        throw;
                    }
                }

                //if the instance returned by MakeGenericMethod does not pass checks that's a dealbreaker!
                if (instance != null)
                {
                    try
                    {
                        //and that it returns an instance
                        Assert.IsNotNull(instance);
                        Assert.IsTrue(instance.Exists());
                        Assert.AreEqual(ChangeDescription.NoChanges, instance.HasLocalChanges().Evaluation, "Type was '" + t.Name + "'");
                    }
                    catch (Exception e)
                    {
                        throw new Exception("Implementation of WhenIHaveA<" + t.Name + "> is flawed", e);
                    }
                }
            }

            Assert.IsEmpty(notSupported, "The following Types were not supported by WhenIHaveA<T>:" + Environment.NewLine + string.Join(Environment.NewLine, notSupported.Select(t => t.Name)));
        }