Blame mono/Contours/Test.cs

80bc9b
/*
80bc9b
    ......... 2015 Ivan Mahonin
80bc9b
80bc9b
    This program is free software: you can redistribute it and/or modify
80bc9b
    it under the terms of the GNU General Public License as published by
80bc9b
    the Free Software Foundation, either version 3 of the License, or
80bc9b
    (at your option) any later version.
80bc9b
80bc9b
    This program is distributed in the hope that it will be useful,
80bc9b
    but WITHOUT ANY WARRANTY; without even the implied warranty of
80bc9b
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
80bc9b
    GNU General Public License for more details.
80bc9b
80bc9b
    You should have received a copy of the GNU General Public License
80bc9b
    along with this program.  If not, see <http: licenses="" www.gnu.org="">.</http:>
80bc9b
*/
80bc9b
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
30455f
        Shape tryCombineShapes(Shape.CombinationMode mode, 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);
30455f
                return Shape.combine(mode, 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
296d46
            if (input.ContainsKey("badA")) a = input["badA"]; else
05068e
                if (input.ContainsKey("a")) a = input["a"];
296d46
            if (input.ContainsKey("badB")) b = input["badB"]; 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) {
30455f
                check("add", tryCombineShapes(Shape.CombinationMode.Add, a, b));
30455f
                check("subtract", tryCombineShapes(Shape.CombinationMode.Subtract, a, b));
30455f
                check("intersection", tryCombineShapes(Shape.CombinationMode.Intersection, a, b));
30455f
                check("xor", tryCombineShapes(Shape.CombinationMode.Xor, 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;
bb5d1a
                for(int j = 1; j < b.Count; ++j) {
bb5d1a
                    if (!compared[j] && 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;
d0a1c2
                for(int j = 0; j < b.Count; ++j) {
bb5d1a
                    if (!compared[j] && 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(); }
80bc9b
7c6265
            void skipSpaces() {
7c6265
                while(position < text.Length && char.IsWhiteSpace(text[position])) ++position;
80bc9b
                if (position < text.Length && text.Substring(position, 2) == "/*") {
80bc9b
                    while(position < text.Length)
80bc9b
                        if (text.Substring(position, 2) == "*/")
80bc9b
                            { position += 2; break; } else ++position;
80bc9b
                    skipSpaces();
80bc9b
                }
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