Blame mono/Contours/Test.cs

7c6265
using System;
7c6265
using System.Collections.Generic;
7c6265
using System.Drawing;
7c6265
7c6265
namespace Contours {
7c6265
    public class Test {
7c6265
        class Exception: System.Exception { }
7c6265
7c6265
        public string name;
7c6265
        
7c6265
        public readonly Dictionary<string, list<list<list<point="">>>> input = new Dictionary<string, list<list<list<point="">>>>();</string,></string,>
7c6265
        public readonly Dictionary<string, list<list<list<point="">>>> output = new Dictionary<string, list<list<list<point="">>>>();</string,></string,>
7c6265
        public readonly Dictionary<string, bool=""> results = new Dictionary<string, bool="">();</string,></string,>
7c6265
        public bool result = false;
7c6265
        
7c6265
        public static readonly List<test> tests = new List<test>();</test></test>
7c6265
        
05068e
        void check(string name, Shape shape) {
05068e
            if (!input.ContainsKey(name)) return;
05068e
            List<list<list<point>>> contours = null;</list<list<point>
05068e
            try {
05068e
                contours = shape.getContours();
05068e
            } catch(System.Exception) { }
05068e
            output.Add(name, contours);
7c6265
            results.Add(name, compareContours(input[name], output[name]));
7c6265
            if (!results[name]) result = false;
7c6265
        }
7c6265
        
05068e
        Shape tryCreateShape(List<list<list<point>>> contours) {</list<list<point>
05068e
            try {
05068e
                Shape shape = new Shape();
05068e
                shape.setContours(contours);
05068e
                return shape;
05068e
            } catch (System.Exception) {
05068e
                return null;
05068e
            }
05068e
        }
05068e
05068e
        delegate Shape CombineShapesFunc(Shape a, Shape b);
05068e
        Shape tryCombineShapes(CombineShapesFunc func, List<list<list<point>>> a, List<list<list<point>>> b) {</list<list<point></list<list<point>
05068e
            try {
05068e
                Shape sa = new Shape();
05068e
                Shape sb = new Shape();
05068e
                sa.setContours(a);
05068e
                sb.setContours(b);
05068e
                return func(sa, sb);
05068e
            } catch (System.Exception) {
05068e
                return null;
05068e
            }
05068e
        }
05068e
                
7c6265
        public bool run() {
7c6265
            result = true;
05068e
            
05068e
            List<list<list<point>>> a = null;</list<list<point>
05068e
            List<list<list<point>>> b = null;</list<list<point>
05068e
05068e
            if (input.ContainsKey("dirtyA")) a = input["dirtyA"]; else
05068e
                if (input.ContainsKey("a")) a = input["a"];
05068e
            if (input.ContainsKey("dirtyB")) b = input["dirtyB"]; else
05068e
                if (input.ContainsKey("b")) b = input["b"];
05068e
            
05068e
            if (a != null)
05068e
                check("a", tryCreateShape(a));
05068e
            if (b != null)
05068e
                check("b", tryCreateShape(b));
05068e
                
05068e
            if (a != null && b != null) {
05068e
                check("add", tryCombineShapes(Shape.add, a, b));
05068e
                check("subtract", tryCombineShapes(Shape.subtract, a, b));
05068e
                check("xor", tryCombineShapes(Shape.xor, a, b));
05068e
                check("intersection", tryCombineShapes(Shape.intersection, a, b));
05068e
            }
05068e
7c6265
            return result;
7c6265
        }
7c6265
7c6265
        public static bool compareContours(List<point> a, List<point> b) {</point></point>
05068e
            if (a == null || b == null) return false;
7c6265
            if (a.Count == b.Count) {
7c6265
                for(int offset = 0; offset < a.Count; ++offset) {
7c6265
                    bool equal = true;
7c6265
                    for(int i = 0; i < a.Count; ++i)
7c6265
                        if (a[(i + offset)%a.Count] != b[i])
7c6265
                            { equal = false; break; }
7c6265
                    if (equal) return true;
7c6265
                }
7c6265
            }
7c6265
            return false;
7c6265
        }
7c6265
7c6265
        public static bool compareContours(List<list<point>> a, List<list<point>> b) {</list<point></list<point>
05068e
            if (a == null || b == null) return false;
7c6265
            if (a.Count != b.Count) return false;
7c6265
            if (a.Count == 0) return true;
7c6265
            if (!compareContours(a[0], b[0])) return false;
7c6265
            bool[] compared = new bool[a.Count];
7c6265
            for(int i = 1; i < a.Count; ++i) {
7c6265
                bool equal = false;
7c6265
                for(int j = i + 1; j < b.Count; ++j) {
7c6265
                    if (!compared[i] && compareContours(a[i], b[j]))
7c6265
                        { equal = true; compared[j] = true; break; }
7c6265
                }
7c6265
                if (!equal) return false;
7c6265
            }
7c6265
            return true;
7c6265
        }
7c6265
7c6265
        public static bool compareContours(List<list<list<point>>> a, List<list<list<point>>> b) {</list<list<point></list<list<point>
05068e
            if (a == null || b == null) return false;
7c6265
            if (a.Count != b.Count) return false;
7c6265
            bool[] compared = new bool[a.Count];
7c6265
            for(int i = 0; i < a.Count; ++i) {
7c6265
                bool equal = false;
7c6265
                for(int j = i + 1; j < b.Count; ++j) {
7c6265
                    if (!compared[i] && compareContours(a[i], b[j]))
7c6265
                        { equal = true; compared[j] = true; break; }
7c6265
                }
7c6265
                if (!equal) return false;
7c6265
            }
7c6265
            return true;
7c6265
        }
7c6265
                
7c6265
        class Loader {
7c6265
            public string text;
7c6265
            public int position = 0;
7c6265
            
7c6265
            void error() { throw new Exception(); }
7c6265
            void assert(bool expr) { if (!expr) error(); }
7c6265
            
7c6265
            void skipSpaces() {
7c6265
                while(position < text.Length && char.IsWhiteSpace(text[position])) ++position;
7c6265
            }
7c6265
            
7c6265
            int loadInt() {
7c6265
                skipSpaces();
7c6265
                int startPosition = position;
7c6265
                while(position < text.Length && char.IsDigit(text[position])) ++position;
7c6265
                assert(startPosition < position);
7c6265
                return int.Parse(text.Substring(startPosition, position-startPosition));
7c6265
            }
7c6265
7c6265
            string tryLoadKey(string key) {
7c6265
                return tryLoadKey(new string[] { key });
7c6265
            }
7c6265
7c6265
            string tryLoadKey(string key0, string key1) {
7c6265
                return tryLoadKey(new string[] { key0, key1 });
7c6265
            }
7c6265
7c6265
            string tryLoadKey(string[] keys) {
7c6265
                skipSpaces();
7c6265
                foreach(string key in keys)
7c6265
                    if (text.Substring(position, key.Length) == key)
7c6265
                        { position += key.Length; return key; }
7c6265
                return null;
7c6265
            }
7c6265
            
7c6265
            string loadKey(string key) {
7c6265
                return loadKey(new string[] { key });
7c6265
            }
7c6265
7c6265
            string loadKey(string key0, string key1) {
7c6265
                return loadKey(new string[] { key0, key1 });
7c6265
            }
7c6265
7c6265
            string loadKey(string[] keys) {
7c6265
                string result = tryLoadKey(keys);
7c6265
                assert(result != null);
7c6265
                return result;
7c6265
            }
7c6265
            
7c6265
            Point loadPoint() {
7c6265
                loadKey("(");
7c6265
                int x = loadInt();
7c6265
                loadKey(",");
7c6265
                int y = loadInt();
7c6265
                loadKey(")");
7c6265
                return new Point(x, y);
7c6265
            }
7c6265
            
7c6265
            List<point> loadPointList() {</point>
7c6265
                List<point> list = new List<point>();</point></point>
7c6265
                loadKey("(");
7c6265
                if (tryLoadKey(")") == null) do {
7c6265
                    list.Add(loadPoint());
7c6265
                } while(loadKey(",", ")") == ",");
7c6265
                return list;
7c6265
            }
7c6265
            
7c6265
            List<list<point>> loadPointListList() {</list<point>
7c6265
                List<list<point>> list = new List<list<point>>();</list<point></list<point>
7c6265
                loadKey("(");
7c6265
                if (tryLoadKey(")") == null) do {
7c6265
                    list.Add(loadPointList());
7c6265
                } while(loadKey(",", ")") == ",");
7c6265
                return list;
7c6265
            }
7c6265
            
7c6265
            List<list<list<point>>> loadPointListListList() {</list<list<point>
7c6265
                List<list<list<point>>> list = new List<list<list<point>>>();</list<list<point></list<list<point>
7c6265
                loadKey("(");
7c6265
                if (tryLoadKey(")") == null) do {
7c6265
                    list.Add(loadPointListList());
7c6265
                } while(loadKey(",", ")") == ",");
7c6265
                return list;
7c6265
            }
7c6265
            
7c6265
            string loadFieldName() {
7c6265
                skipSpaces();
7c6265
                int startPosition = position;
7c6265
                while(position < text.Length && char.IsLetterOrDigit(text[position])) ++position;
7c6265
                assert(startPosition < position);
7c6265
                return text.Substring(startPosition, position-startPosition);
7c6265
            }
7c6265
7c6265
            string loadName() {
7c6265
                string name = "";
7c6265
                loadKey("(");
05068e
                while(text[position] != ')')
7c6265
                    name += text[position++];
05068e
                ++position;
7c6265
                return name.Trim();
7c6265
            }
7c6265
7c6265
            Test loadTest() {
7c6265
                Test test = new Test();
7c6265
                loadKey("{");
7c6265
                while(tryLoadKey("}") == null) {
7c6265
                    string name = loadFieldName();
7c6265
                    loadKey(":");
7c6265
                    if (name == "name")
7c6265
                        test.name = loadName();
7c6265
                    else
7c6265
                        test.input.Add(name, loadPointListListList());
7c6265
                }
7c6265
                return test;
7c6265
            }
7c6265
7c6265
            public List<test> loadTestListToEof() {</test>
7c6265
                List<test> list = new List<test>();</test></test>
7c6265
                while(true) {
7c6265
                    skipSpaces();
7c6265
                    if (position >= text.Length) break;
7c6265
                    list.Add(loadTest());
7c6265
                }
7c6265
                return list;
7c6265
            }
7c6265
        };
7c6265
        
7c6265
        static void loadTests(string text) {
7c6265
            Loader loader = new Loader();
7c6265
            loader.text = text;
7c6265
            tests.Clear();
7c6265
            tests.AddRange(loader.loadTestListToEof());
7c6265
        }
7c6265
        
7c6265
        public static void loadTestsFromFile(string filename) {
7c6265
            loadTests(System.IO.File.ReadAllText(filename));
7c6265
        }
7c6265
        
7c6265
        public static bool runAll() {
7c6265
            bool result = true;
7c6265
            foreach(Test test in tests)
7c6265
                if (!test.run()) result = false;
7c6265
            return result;
7c6265
        }
7c6265
7c6265
        static string resultToString(string name, bool result) {
7c6265
            return name + ": " + (result ? "+" : "FAILED") + "\n";
7c6265
        }
7c6265
7c6265
        public static string makeReport() {
7c6265
            string report = "";
7c6265
            foreach(Test test in tests) {
7c6265
                report += resultToString(test.name, test.result);
7c6265
                foreach(KeyValuePair<string, bool=""> pair in test.results)</string,>
7c6265
                    report += resultToString("    " + pair.Key, pair.Value);
7c6265
            }
7c6265
            return report;
7c6265
        }
7c6265
        
7c6265
        public static void saveReport(string filename) {
7c6265
            System.IO.File.WriteAllText(filename, makeReport());
7c6265
        }
7c6265
    }
7c6265
}
7c6265