Free cookie consent management tool by TermsFeed Policy Generator

source: branches/GeneralizedQAP/HeuristicLab/3.3/Tests/DeepCloneableCloningTest.cs @ 6780

Last change on this file since 6780 was 6685, checked in by abeham, 13 years ago

#1628

  • Updated branch from trunk
  • Changed ReferenceEqualityComparer<T> to become a non-generic class (generic implementation probably was only made because of lacking support for co- and contravariance in C# 3.5)
  • Added finished experiment from sample algorithms to the tests
  • Wrote a unit test to instantiate every IDeepCloneable type, clone it and compare the objects in the object graph for equal references
  • Wrote a unit test to load the experiment, clone it and compare again the objects in the object graph
  • Preliminary fix for a potential bug in ThreadSafeLog
  • Preliminary fix for a potential bug in OperatorGraphVisualizationInfo
  • Preliminary fix for a potential bug in Calculator (and added license headers)
  • Preliminary fix for a potential bug in ScrambleMove
File size: 6.1 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Threading;
26using HeuristicLab.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Optimization;
29using HeuristicLab.Persistence.Default.Xml;
30using HeuristicLab.PluginInfrastructure;
31using Microsoft.VisualStudio.TestTools.UnitTesting;
32
33namespace HeuristicLab_33.Tests {
34  /// <summary>
35  /// Summary description for DeepCloneableCloningTest
36  /// </summary>
37  [TestClass]
38  public class DeepCloneableCloningTest {
39
40    public DeepCloneableCloningTest() {
41      excludedTypes = new HashSet<Type>();
42      excludedTypes.Add(typeof(HeuristicLab.Problems.DataAnalysis.Dataset));
43      excludedTypes.Add(typeof(HeuristicLab.Problems.TravelingSalesman.DistanceMatrix));
44    }
45
46    private TestContext testContextInstance;
47    private HashSet<Type> excludedTypes;
48
49    /// <summary>
50    ///Gets or sets the test context which provides
51    ///information about and functionality for the current test run.
52    ///</summary>
53    public TestContext TestContext {
54      get {
55        return testContextInstance;
56      }
57      set {
58        testContextInstance = value;
59      }
60    }
61
62    #region Additional test attributes
63    //
64    // You can use the following additional attributes as you write your tests:
65    //
66    // Use ClassInitialize to run code before running the first test in the class
67    // [ClassInitialize()]
68    // public static void MyClassInitialize(TestContext testContext) { }
69    //
70    // Use ClassCleanup to run code after all tests in a class have run
71    // [ClassCleanup()]
72    // public static void MyClassCleanup() { }
73    //
74    // Use TestInitialize to run code before running each test
75    // [TestInitialize()]
76    // public void MyTestInitialize() { }
77    //
78    // Use TestCleanup to run code after each test has run
79    // [TestCleanup()]
80    // public void MyTestCleanup() { }
81    //
82    #endregion
83
84    private ManualResetEvent waitHandle;
85
86    [TestMethod]
87    [DeploymentItem("SamplesExperimentFinished.hl")]
88    public void TestCloningFinishedExperiment() {
89      waitHandle = new ManualResetEvent(false);
90      Experiment experiment = (Experiment)XmlParser.Deserialize("SamplesExperimentFinished.hl");
91
92      Experiment clone = (Experiment)experiment.Clone(new Cloner());
93      var intersections = CheckTotalInequality(experiment, clone).Where(x => x.GetType().FullName.StartsWith("HeuristicLab"));
94
95      Assert.IsTrue(ProcessEqualObjects(experiment, intersections));
96    }
97
98    private void batchrun_Stopped(object sender, EventArgs e) {
99      waitHandle.Set();
100    }
101
102    [TestMethod]
103    public void TestCloningAllDeepCloneables() {
104      PluginLoader.Assemblies.ToArray();
105      bool success = true;
106      foreach (Type deepCloneableType in ApplicationManager.Manager.GetTypes(typeof(IDeepCloneable))) {
107        // skip types that explicitely choose not to deep-clone every member
108        if (excludedTypes.Contains(deepCloneableType)) continue;
109        // test only types contained in HL plugin assemblies
110        if (!PluginLoader.Assemblies.Contains(deepCloneableType.Assembly)) continue;
111        // test only instantiable types
112        if (deepCloneableType.IsAbstract || !deepCloneableType.IsClass) continue;
113
114        IDeepCloneable item = null;
115        try {
116          item = (IDeepCloneable)Activator.CreateInstance(deepCloneableType, nonPublic: true);
117        } catch { continue; } // no default constructor
118
119        IDeepCloneable clone = (IDeepCloneable)item.Clone(new Cloner());
120        var intersections = CheckTotalInequality(item, clone).Where(x => x.GetType().FullName.StartsWith("HeuristicLab"));
121        if (!intersections.Any()) continue;
122
123        if (!ProcessEqualObjects(item, intersections))
124          success = false;
125      }
126      Assert.IsTrue(success, "There are potential errors in deep cloning objects.");
127    }
128
129    private IEnumerable<object> CheckTotalInequality(object original, object clone) {
130      HashSet<object> originalObjects = new HashSet<object>(original.GetObjectGraphObjects().Where(x => !x.GetType().IsValueType), new ReferenceEqualityComparer());
131      HashSet<object> clonedObjects = new HashSet<object>(clone.GetObjectGraphObjects().Where(x => !x.GetType().IsValueType), new ReferenceEqualityComparer());
132
133      return originalObjects.Intersect(clonedObjects);
134    }
135
136    private bool ProcessEqualObjects(IDeepCloneable item, IEnumerable<object> intersections) {
137      bool success = true;
138      TestContext.WriteLine(Environment.NewLine + item.GetType().FullName + ":");
139      foreach (object o in intersections) {
140        string typeName = o.GetType().FullName;
141        if (excludedTypes.Contains(o.GetType())) {
142          TestContext.WriteLine("Skipping excluded type " + typeName);
143        } else if (o is IDeepCloneable) {
144          string info = (o is IItem) ? ((IItem)o).ItemName + ((o is INamedItem) ? ", " + ((INamedItem)o).Name : String.Empty) : String.Empty;
145          TestContext.WriteLine("POTENTIAL ERROR! A DEEPCLONEABLE WAS NOT DEEP CLONED (" + info + "): " + typeName);
146          success = false;
147        } else
148          TestContext.WriteLine("WARNING: An object of type " + typeName + " is referenced in the original and in the clone.");
149      }
150      return success;
151    }
152  }
153}
Note: See TracBrowser for help on using the repository browser.