Blame mono/Contours/Test.cs

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