From 27ea615c3dca4465f6fce8441e909b6b59639411 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 28 Feb 2011 18:04:47 +0100 Subject: [PATCH] Add regression tests for the c++ binding. --- tests2/Makefile.am | 31 +++++++++++ tests2/README | 3 ++ tests2/TestDriver.cs | 125 +++++++++++++++++++++++++++++++++++++++++++ tests2/test.cpp | 36 +++++++++++++ tests2/test.cs | 66 +++++++++++++++++++++++ tests2/test.h | 73 +++++++++++++++++++++++++ 6 files changed, 334 insertions(+) create mode 100644 tests2/Makefile.am create mode 100644 tests2/README create mode 100644 tests2/TestDriver.cs create mode 100644 tests2/test.cpp create mode 100644 tests2/test.cs create mode 100644 tests2/test.h diff --git a/tests2/Makefile.am b/tests2/Makefile.am new file mode 100644 index 00000000..d6fa0828 --- /dev/null +++ b/tests2/Makefile.am @@ -0,0 +1,31 @@ +top_srcdir = ../ + +INTEROP_DLL = \ + $(top_srcdir)/src/Mono.VisualC.Interop/bin/Debug/Mono.VisualC.Interop.dll + +all: test.exe + +test.xml: test.h + gccxml -fxml=$@ --gccxml-cxxflags -c test.h + +libTest.so: test.h test.cpp + g++ -fPIC --shared -o $@ test.cpp + +libTest-inline.so: test.h test.cpp + g++ -fPIC --shared -fkeep-inline-functions -o $@ test.cpp + +generated: test.xml + $(RM) -r generated + mono --debug $(top_srcdir)/src/generator2/bin/Debug/generator.exe -o=generated -ns=CppTests -lib=Test test.xml + +CppTestBinding.dll: generated + mcs -out:$@ -target:library -unsafe -r:$(INTEROP_DLL) generated/*.cs + +test.exe: test.cs TestDriver.cs CppTestBinding.dll libTest.so libTest-inline.so + mcs -out:$@ -target:exe -r:$(INTEROP_DLL) -r:CppTestBinding.dll test.cs TestDriver.cs + +clean: + $(RM) -rf CppTestBinding.dll test.exe generated libTest.so libTest-inline.so test.xml + +run: test.exe + MONO_PATH=$(top_srcdir)/src/Mono.VisualC.Interop/bin/Debug mono test.exe \ No newline at end of file diff --git a/tests2/README b/tests2/README new file mode 100644 index 00000000..3f034897 --- /dev/null +++ b/tests2/README @@ -0,0 +1,3 @@ +This directory contains tests for the cpp binding. It should probably be merged with +src/Tests. To run them, type 'make run'. + diff --git a/tests2/TestDriver.cs b/tests2/TestDriver.cs new file mode 100644 index 00000000..d7e3252f --- /dev/null +++ b/tests2/TestDriver.cs @@ -0,0 +1,125 @@ +using System; +using System.Reflection; +using System.Collections.Generic; + +public class CategoryAttribute : Attribute +{ + public CategoryAttribute (string category) { + Category = category; + } + + public string Category { + get; set; + } +} + +public class TestDriver { + + static public int RunTests (Type type, string[] args) { + int failed = 0, ran = 0; + int result, expected; + int i, j, iterations; + string name; + MethodInfo[] methods; + bool do_timings = false; + bool verbose = false; + int tms = 0; + DateTime start, end = DateTime.Now; + + iterations = 1; + + var exclude = new Dictionary (); + List run_only = new List (); + if (args != null && args.Length > 0) { + for (j = 0; j < args.Length;) { + if (args [j] == "--time") { + do_timings = true; + j ++; + } else if (args [j] == "--iter") { + iterations = Int32.Parse (args [j + 1]); + j += 2; + } else if ((args [j] == "-v") || (args [j] == "--verbose")) { + verbose = true; + } else if (args [j] == "--exclude") { + exclude [args [j + 1]] = args [j + 1]; + j += 2; + } else if (args [j] == "--run-only") { + run_only.Add (args [j + 1]); + j += 2; + } else { + Console.WriteLine ("Unknown argument: " + args [j]); + return 1; + } + } + } + int nskipped = 0; + methods = type.GetMethods (BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static); + for (int iter = 0; iter < iterations; ++iter) { + for (i = 0; i < methods.Length; ++i) { + name = methods [i].Name; + if (!name.StartsWith ("test_", StringComparison.Ordinal)) + continue; + if (run_only.Count > 0) { + bool found = false; + for (j = 0; j < run_only.Count; j++) { + if (name.EndsWith (run_only [j])) { + found = true; + break; + } + } + if (!found) + continue; + } + if (exclude.Count > 0) { + var attrs = methods [i].GetCustomAttributes (typeof (CategoryAttribute), false); + bool skip = false; + foreach (CategoryAttribute attr in attrs) { + if (exclude.ContainsKey (attr.Category)) + skip = true; + } + if (skip) { + if (verbose) + Console.WriteLine ("Skipping '{0}'.", name); + nskipped ++; + continue; + } + } + for (j = 5; j < name.Length; ++j) + if (!Char.IsDigit (name [j])) + break; + if (verbose) + Console.WriteLine ("Running '{0}' ...", name); + expected = Int32.Parse (name.Substring (5, j - 5)); + start = DateTime.Now; + result = (int)methods [i].Invoke (null, null); + if (do_timings) { + end = DateTime.Now; + long tdiff = end.Ticks - start.Ticks; + int mdiff = (int)tdiff/10000; + tms += mdiff; + Console.WriteLine ("{0} took {1} ms", name, mdiff); + } + ran++; + if (result != expected) { + failed++; + Console.WriteLine ("{0} failed: got {1}, expected {2}", name, result, expected); + } + } + + if (do_timings) { + Console.WriteLine ("Total ms: {0}", tms); + } + if (nskipped > 0) + Console.WriteLine ("Regression tests: {0} ran, {1} skipped, {2} failed in {3}", ran, nskipped, failed, type); + else + Console.WriteLine ("Regression tests: {0} ran, {1} failed in {2}", ran, failed, type); + } + + //Console.WriteLine ("Regression tests: {0} ran, {1} failed in [{2}]{3}", ran, failed, type.Assembly.GetName().Name, type); + return failed; + } + static public int RunTests (Type type) { + return RunTests (type, null); + } +} + diff --git a/tests2/test.cpp b/tests2/test.cpp new file mode 100644 index 00000000..0d1c562d --- /dev/null +++ b/tests2/test.cpp @@ -0,0 +1,36 @@ + +#include "test.h" + +ClassWithCopyCtor::ClassWithCopyCtor(const ClassWithCopyCtor& f) { + x = f.x; +} + +ClassWithCopyCtor +ClassWithCopyCtor::Return (int x) { + return ClassWithCopyCtor (x); +} + +int +ClassWithCopyCtor::GetX () { + return x; +} + +ClassWithDtor +ClassWithDtor::Return (int x) { + return ClassWithDtor (x); +} + +int +ClassWithDtor::GetX () { + return x; +} + +ClassWithoutCopyCtor +ClassWithoutCopyCtor::Return (int x) { + return ClassWithoutCopyCtor (x); +} + +int +ClassWithoutCopyCtor::GetX () { + return x; +} diff --git a/tests2/test.cs b/tests2/test.cs new file mode 100644 index 00000000..a6468a41 --- /dev/null +++ b/tests2/test.cs @@ -0,0 +1,66 @@ +using System; +using CppTests; + +public class Tests +{ + public static void Main (String[] args) { + TestDriver.RunTests (typeof (Tests), args); + } + + public static int test_0_class_return () { + // Section 3.1.4: + // Classes with non-default copy ctors/destructors are returned using a hidden + // argument + var c = ClassWithCopyCtor.Return (42); + if (c.GetX () != 42) + return 1; + + var c2 = ClassWithDtor.Return (43); + if (c2.GetX () != 43) + return 2; + + // This class is returned normally + var c3 = ClassWithoutCopyCtor.Return (44); + if (c3.GetX () != 44) + return 3; + return 0; + } + + // An object as ref argument + public static int test_0_class_arg () { + var c1 = new Class (4); + var c2 = new Class (5); + + c1.CopyTo (c2); + return c2.GetX () == 4 ? 0 : 1; + } + + // A null object as ref argument + public static int test_0_class_arg_null () { + var c1 = new Class (4); + + return c1.IsNull (null) ? 0 : 1; + } + + // An object as byval argument + public static int test_0_class_arg_byval () { + var c1 = new Class (4); + var c2 = new Class (5); + + c1.CopyFromValue (c2); + return c1.GetX () == 5 ? 0 : 1; + } + + // A null object as byval argument + public static int test_0_class_arg_byval_null () { + var c1 = new Class (4); + + try { + c1.CopyFromValue (null); + } catch (ArgumentException) { + return 0; + } + return 1; + } + +} diff --git a/tests2/test.h b/tests2/test.h new file mode 100644 index 00000000..dc9ca969 --- /dev/null +++ b/tests2/test.h @@ -0,0 +1,73 @@ + +class ClassWithCopyCtor { + int x; + +public: + ClassWithCopyCtor(int xarg) { + x = xarg; + } + + ClassWithCopyCtor(const ClassWithCopyCtor& f); + + static ClassWithCopyCtor Return (int x); + + int GetX (); +}; + +class ClassWithDtor { + int x; + +public: + ClassWithDtor(int xarg) { + x = xarg; + } + + ~ClassWithDtor () { + } + + static ClassWithDtor Return (int x); + + int GetX (); +}; + + +class ClassWithoutCopyCtor { + int x; + +public: + ClassWithoutCopyCtor(int xarg) { + x = xarg; + } + + static ClassWithoutCopyCtor Return (int x); + + int GetX (); +}; + +class Class { + int x; + +public: + Class (int xarg) { + x = xarg; + } + + void CopyFromValue (Class c) { + x = c.x; + } + + void CopyTo (Class *c) { + c->x = x; + } + + bool IsNull (Class *c) { + return !c ? true : false; + } + + int GetX () { + return x; + } +}; + + +