From 7c62656d71d32fe558d2dcc67c936c120d640801 Mon Sep 17 00:00:00 2001 From: Ivan Mahonin Date: Apr 18 2015 10:13:08 +0000 Subject: Tests --- diff --git a/mono/Contours/Contours.csproj b/mono/Contours/Contours.csproj index 5c4af5f..2a081d3 100644 --- a/mono/Contours/Contours.csproj +++ b/mono/Contours/Contours.csproj @@ -37,6 +37,7 @@ + @@ -47,4 +48,9 @@ + + + Always + + \ No newline at end of file diff --git a/mono/Contours/MainForm.cs b/mono/Contours/MainForm.cs index bdfabcc..7d52e58 100644 --- a/mono/Contours/MainForm.cs +++ b/mono/Contours/MainForm.cs @@ -6,7 +6,30 @@ using System.Drawing; namespace Contours { public class MainForm: Form { + Button bTest; + ComboBox cbTests; + ComboBox cbViews; + public MainForm() { + bTest = new Button(); + bTest.Left = 20; + bTest.Top = 20; + bTest.Text = "test"; + bTest.Click += bTestClicked; + Controls.Add(bTest); + + cbTests = new ComboBox(); + cbTests.Left = bTest.Right + 20; + cbTests.Top = 20; + cbTests.SelectedIndexChanged += cbTestsChanged; + Controls.Add(cbTests); + + cbViews = new ComboBox(); + cbViews.Left = cbTests.Right + 20; + cbViews.Top = 20; + cbViews.SelectedIndexChanged += cbViewsChanged; + Controls.Add(cbViews); + MouseDown += mouseDown; MouseMove += mouseMove; MouseUp += mouseUp; @@ -16,6 +39,33 @@ namespace Contours { bool drawing = false; List> contours = new List>(); + void bTestClicked(object sender, EventArgs e) { + Test.loadTestsFromFile("tests.txt"); + bool success = Test.runAll(); + Test.saveReport("report.txt"); + + foreach(Test test in Test.tests) + cbTests.Items.Add(test.name); + + if (!success) MessageBox.Show("Tests failed"); + } + + void cbTestsChanged(object sender, EventArgs e) { + cbViews.Items.Clear(); + foreach(Test test in Test.tests) { + if (cbTests.Text == test.name) { + foreach(string name in test.input.Keys) + cbViews.Items.Add("i: " + name); + foreach(string name in test.output.Keys) + cbViews.Items.Add("o: " + name); + } + } + } + + void cbViewsChanged(object sender, EventArgs e) { + Refresh(); + } + private void mouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { contours.Add(new List()); @@ -43,12 +93,44 @@ namespace Contours { } } + void drawContour(Graphics g, Color color, List c) { + if (c != null && c.Count >= 3) { + g.DrawLines(new Pen(new SolidBrush(color)), c.ToArray()); + g.DrawLine(new Pen(new SolidBrush(color)), c.First(), c.Last()); + } + } + + void drawContour(Graphics g, Color color, List c) { + if (c != null && c.Count >= 3) { + g.DrawLines(new Pen(new SolidBrush(color)), c.ToArray()); + g.DrawLine(new Pen(new SolidBrush(color)), c.First(), c.Last()); + } + } + private void paint(object sender, PaintEventArgs e) { e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; - foreach(List c in contours) { - if (c != null && c.Count >= 3) { - e.Graphics.DrawLines(Pens.Black, c.ToArray()); - e.Graphics.DrawLine(Pens.Black, c.First(), c.Last()); + foreach(List c in contours) + drawContour(e.Graphics, Color.Gray, c); + + List>> testContours = null; + foreach(Test test in Test.tests) { + if (cbTests.Text == test.name) { + foreach(KeyValuePair>>> pair in test.input) + if (cbViews.Text == "i: " + pair.Key) + testContours = pair.Value; + foreach(KeyValuePair>>> pair in test.output) + if (cbViews.Text == "o: " + pair.Key) + testContours = pair.Value; + } + } + + if (testContours != null) { + foreach(List> group in testContours) { + Color color = Color.Black; + foreach(List c in group) { + drawContour(e.Graphics, color, c); + color = Color.Blue; + } } } } diff --git a/mono/Contours/Shape.cs b/mono/Contours/Shape.cs index 099ea8b..ed62ecf 100644 --- a/mono/Contours/Shape.cs +++ b/mono/Contours/Shape.cs @@ -5,6 +5,8 @@ using System.Drawing; namespace Contours { public class Shape { + class Exception: System.Exception { } + class Position { public Point point; public readonly Circuit links; @@ -77,6 +79,13 @@ namespace Contours { setContours(new IEnumerable[] { contour }); } + public void setContours(IEnumerable>> contours) { + List> list = new List>(); + foreach(IEnumerable> c in contours) + list.AddRange(c); + setContours(list); + } + public void setContours(IEnumerable> contours) { clear(); foreach(IEnumerable contour in contours) { diff --git a/mono/Contours/Test.cs b/mono/Contours/Test.cs new file mode 100644 index 0000000..cb00ac3 --- /dev/null +++ b/mono/Contours/Test.cs @@ -0,0 +1,243 @@ +using System; +using System.Collections.Generic; +using System.Drawing; + +namespace Contours { + public class Test { + class Exception: System.Exception { } + + public string name; + + public readonly Dictionary>>> input = new Dictionary>>>(); + public readonly Dictionary>>> output = new Dictionary>>>(); + public readonly Dictionary results = new Dictionary(); + public bool result = false; + + public static readonly List tests = new List(); + + void check(string name, List>> calculatedContours) { + output.Add(name, calculatedContours); + results.Add(name, compareContours(input[name], output[name])); + if (!results[name]) result = false; + } + + public bool run() { + result = true; + Shape a = new Shape(); + Shape b = new Shape(); + a.setContours(input["a"]); + b.setContours(input["b"]); + check("add", Shape.add(a, b).getContours()); + check("subtract", Shape.subtract(a, b).getContours()); + check("xor", Shape.xor(a, b).getContours()); + check("intersection", Shape.intersection(a, b).getContours()); + return result; + } + + public static bool compareContours(List a, List b) { + if (a.Count == b.Count) { + for(int offset = 0; offset < a.Count; ++offset) { + bool equal = true; + for(int i = 0; i < a.Count; ++i) + if (a[(i + offset)%a.Count] != b[i]) + { equal = false; break; } + if (equal) return true; + } + } + return false; + } + + public static bool compareContours(List> a, List> b) { + if (a.Count != b.Count) return false; + if (a.Count == 0) return true; + if (!compareContours(a[0], b[0])) return false; + bool[] compared = new bool[a.Count]; + for(int i = 1; i < a.Count; ++i) { + bool equal = false; + for(int j = i + 1; j < b.Count; ++j) { + if (!compared[i] && compareContours(a[i], b[j])) + { equal = true; compared[j] = true; break; } + } + if (!equal) return false; + } + return true; + } + + public static bool compareContours(List>> a, List>> b) { + if (a.Count != b.Count) return false; + bool[] compared = new bool[a.Count]; + for(int i = 0; i < a.Count; ++i) { + bool equal = false; + for(int j = i + 1; j < b.Count; ++j) { + if (!compared[i] && compareContours(a[i], b[j])) + { equal = true; compared[j] = true; break; } + } + if (!equal) return false; + } + return true; + } + + class Loader { + public string text; + public int position = 0; + + void error() { throw new Exception(); } + void assert(bool expr) { if (!expr) error(); } + + void skipSpaces() { + while(position < text.Length && char.IsWhiteSpace(text[position])) ++position; + } + + int loadInt() { + skipSpaces(); + int startPosition = position; + while(position < text.Length && char.IsDigit(text[position])) ++position; + assert(startPosition < position); + return int.Parse(text.Substring(startPosition, position-startPosition)); + } + + string tryLoadKey(string key) { + return tryLoadKey(new string[] { key }); + } + + string tryLoadKey(string key0, string key1) { + return tryLoadKey(new string[] { key0, key1 }); + } + + string tryLoadKey(string[] keys) { + skipSpaces(); + foreach(string key in keys) + if (text.Substring(position, key.Length) == key) + { position += key.Length; return key; } + return null; + } + + string loadKey(string key) { + return loadKey(new string[] { key }); + } + + string loadKey(string key0, string key1) { + return loadKey(new string[] { key0, key1 }); + } + + string loadKey(string[] keys) { + string result = tryLoadKey(keys); + assert(result != null); + return result; + } + + Point loadPoint() { + loadKey("("); + int x = loadInt(); + loadKey(","); + int y = loadInt(); + loadKey(")"); + return new Point(x, y); + } + + List loadPointList() { + List list = new List(); + loadKey("("); + if (tryLoadKey(")") == null) do { + list.Add(loadPoint()); + } while(loadKey(",", ")") == ","); + return list; + } + + List> loadPointListList() { + List> list = new List>(); + loadKey("("); + if (tryLoadKey(")") == null) do { + list.Add(loadPointList()); + } while(loadKey(",", ")") == ","); + return list; + } + + List>> loadPointListListList() { + List>> list = new List>>(); + loadKey("("); + if (tryLoadKey(")") == null) do { + list.Add(loadPointListList()); + } while(loadKey(",", ")") == ","); + return list; + } + + string loadFieldName() { + skipSpaces(); + int startPosition = position; + while(position < text.Length && char.IsLetterOrDigit(text[position])) ++position; + assert(startPosition < position); + return text.Substring(startPosition, position-startPosition); + } + + string loadName() { + string name = ""; + loadKey("("); + while(tryLoadKey(")") == null) + name += text[position++]; + return name.Trim(); + } + + Test loadTest() { + Test test = new Test(); + loadKey("{"); + while(tryLoadKey("}") == null) { + string name = loadFieldName(); + loadKey(":"); + if (name == "name") + test.name = loadName(); + else + test.input.Add(name, loadPointListListList()); + } + return test; + } + + public List loadTestListToEof() { + List list = new List(); + while(true) { + skipSpaces(); + if (position >= text.Length) break; + list.Add(loadTest()); + } + return list; + } + }; + + static void loadTests(string text) { + Loader loader = new Loader(); + loader.text = text; + tests.Clear(); + tests.AddRange(loader.loadTestListToEof()); + } + + public static void loadTestsFromFile(string filename) { + loadTests(System.IO.File.ReadAllText(filename)); + } + + public static bool runAll() { + bool result = true; + foreach(Test test in tests) + if (!test.run()) result = false; + return result; + } + + static string resultToString(string name, bool result) { + return name + ": " + (result ? "+" : "FAILED") + "\n"; + } + + public static string makeReport() { + string report = ""; + foreach(Test test in tests) { + report += resultToString(test.name, test.result); + foreach(KeyValuePair pair in test.results) + report += resultToString(" " + pair.Key, pair.Value); + } + return report; + } + + public static void saveReport(string filename) { + System.IO.File.WriteAllText(filename, makeReport()); + } + } +} + diff --git a/mono/Contours/tests.txt b/mono/Contours/tests.txt new file mode 100644 index 0000000..86d1dce --- /dev/null +++ b/mono/Contours/tests.txt @@ -0,0 +1,17 @@ +{ + name: + (Two squares) + a: + ( ( ((0, 0), (200, 0), (200, 200), (0, 200)) ) ) + b: + ((((100, 100), (300, 100), (300, 300), (100, 300)))) + add: + ((((0, 0), (200, 0), (200, 100), (300, 100), (300, 300), (100, 300), (100, 200), (0, 200)))) + subtract: + ((((0, 0), (200, 0), (200, 100), (100, 100), (100, 200), (0, 200)))) + xor: + (( ((0, 0), (200, 0), (200, 100), (100, 100), (100, 200), (0, 200)), + ((200, 200), (200, 100), (300, 100), (300, 300), (100, 300), (100, 200)) )) + intersection: + ((((100, 100), (200, 100), (200, 200), (100, 200)))) +}