adds desktop java junit tests
authorEric Christiansen <ericmartinchristiansen@gmail.com>
Wed, 19 Dec 2012 22:28:59 +0000 (14:28 -0800)
committerEric Christiansen <ericmartinchristiansen@gmail.com>
Wed, 19 Dec 2012 22:28:59 +0000 (14:28 -0800)
modules/java/CMakeLists.txt
modules/java/java_test/CMakeLists.txt [new file with mode: 0644]
modules/java/java_test/build.xml [new file with mode: 0644]
modules/java/java_test/lib/junit-4.11.jar [new file with mode: 0644]
modules/java/java_test/src/org/opencv/test/OpenCVTestCase.java [new file with mode: 0644]
modules/java/java_test/src/org/opencv/test/OpenCVTestRunner.java [new file with mode: 0644]

index ee1ad30813da4d9dc6d95a7b9c2b8c6ce94d628d..372bf84d7bec0e3c719f9640033b5ee2ed26496c 100644 (file)
@@ -295,7 +295,12 @@ endif(ANDROID)
 add_dependencies(${lib_target} ${api_target})
 add_dependencies(${the_module} ${lib_target})
 
-#android test project
+# android test project
 if(ANDROID AND BUILD_TESTS)
   add_subdirectory(android_test)
 endif()
+
+# Desktop Java test project.
+if((NOT ANDROID) AND BUILD_TESTS)
+  add_subdirectory(java_test)
+endif()
diff --git a/modules/java/java_test/CMakeLists.txt b/modules/java/java_test/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e912b0d
--- /dev/null
@@ -0,0 +1,80 @@
+ocv_check_dependencies(opencv_java ${OPENCV_MODULE_opencv_java_OPT_DEPS} ${OPENCV_MODULE_opencv_java_REQ_DEPS})
+
+if(NOT OCV_DEPENDENCIES_FOUND OR NOT ANT_EXECUTABLE)
+  return()
+endif()
+
+# TODO: This has the same name as the Android test project. That project should
+# probably be renamed.
+project(opencv_test_java)
+
+set(opencv_test_java_bin_dir "${CMAKE_CURRENT_BINARY_DIR}/.build")
+
+set(android_source_dir "${CMAKE_CURRENT_SOURCE_DIR}/../android_test")
+
+set(java_source_dir ${CMAKE_CURRENT_SOURCE_DIR})
+
+# get project sources
+file(GLOB_RECURSE opencv_test_java_files RELATIVE "${android_source_dir}" "${android_source_dir}/res/*" "${android_source_dir}/src/*")
+ocv_list_filterout(opencv_test_java_files ".svn")
+ocv_list_filterout(opencv_test_java_files ".*#.*")
+# These are the files that need to be updated for pure Java.
+ocv_list_filterout(opencv_test_java_files ".*OpenCVTestCase.*")
+ocv_list_filterout(opencv_test_java_files ".*OpenCVTestRunner.*")
+# These files aren't for desktop Java.
+ocv_list_filterout(opencv_test_java_files ".*android.*")
+
+# These are files updated for pure Java.
+file(GLOB_RECURSE modified_files RELATIVE "${java_source_dir}" "${java_source_dir}/src/*")
+ocv_list_filterout(modified_files ".svn")
+ocv_list_filterout(modified_files ".*#.*")
+
+# These are extra jars needed to run the tests.
+file(GLOB_RECURSE lib_files RELATIVE "${java_source_dir}" "${java_source_dir}/lib/*")
+ocv_list_filterout(lib_files ".svn")
+ocv_list_filterout(lib_files ".*#.*")
+
+# copy sources out from the build tree
+set(opencv_test_java_file_deps "")
+foreach(f ${opencv_test_java_files})
+  add_custom_command(
+      OUTPUT "${opencv_test_java_bin_dir}/${f}"
+      COMMAND ${CMAKE_COMMAND} -E copy "${android_source_dir}/${f}" "${opencv_test_java_bin_dir}/${f}"
+      MAIN_DEPENDENCY "${android_source_dir}/${f}"
+      COMMENT "Copying ${f}")
+  list(APPEND opencv_test_java_file_deps "${android_source_dir}/${f}" "${opencv_test_java_bin_dir}/${f}")
+endforeach()
+
+# Overwrite select Android sources with Java-specific sources.
+# Also, copy over the libs we'll need for testing.
+foreach(f ${modified_files} ${lib_files})
+  add_custom_command(
+      OUTPUT "${opencv_test_java_bin_dir}/${f}"
+      COMMAND ${CMAKE_COMMAND} -E copy "${java_source_dir}/${f}" "${opencv_test_java_bin_dir}/${f}"
+      MAIN_DEPENDENCY "${java_source_dir}/${f}"
+      COMMENT "Copying ${f}")
+  list(APPEND opencv_test_java_file_deps "${java_source_dir}/${f}")
+endforeach()
+
+# Copy the OpenCV jar after it has been generated.
+add_custom_command(
+  OUTPUT "${opencv_test_java_bin_dir}/bin/${JAR_NAME}"
+  COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_BINARY_DIR}/bin/${JAR_NAME}" "${opencv_test_java_bin_dir}/bin/${JAR_NAME}"
+  COMMENT "Copying the OpenCV jar")
+add_custom_target(copy_opencv_jar ALL SOURCES "${opencv_test_java_bin_dir}/bin/${JAR_NAME}")
+# ${the_module} is the target for the Java jar.
+add_dependencies(copy_opencv_jar ${the_module})
+
+# Copy the ant build file.
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/build.xml" DESTINATION "${opencv_test_java_bin_dir}")
+
+# Create a script for running the Java tests and place it in build/bin.
+if(WIN32)
+  file(WRITE "${CMAKE_BINARY_DIR}/bin/opencv_test_java.cmd" "cd ${opencv_test_java_bin_dir}\nset path=${EXECUTABLE_OUTPUT_PATH};%path%\nant -DjavaLibraryPath=${EXECUTABLE_OUTPUT_PATH}/Release buildAndTest")
+  file(WRITE "${CMAKE_BINARY_DIR}/bin/opencv_test_java_D.cmd" "cd ${opencv_test_java_bin_dir}\nset path=${EXECUTABLE_OUTPUT_PATH};%path%\nant -DjavaLibraryPath=${EXECUTABLE_OUTPUT_PATH}/Debug buildAndTest")
+else()
+  file(WRITE "${CMAKE_BINARY_DIR}/bin/opencv_test_java.sh" "cd ${opencv_test_java_bin_dir};\nant -DjavaLibraryPath=${LIBRARY_OUTPUT_PATH} buildAndTest;\ncd -")
+endif()
+
+add_custom_target(${PROJECT_NAME} ALL SOURCES ${opencv_test_java_file_deps})
+add_dependencies(opencv_tests ${PROJECT_NAME})
diff --git a/modules/java/java_test/build.xml b/modules/java/java_test/build.xml
new file mode 100644 (file)
index 0000000..29398b4
--- /dev/null
@@ -0,0 +1,70 @@
+<project>
+  <path id="master-classpath">
+    <fileset dir="lib">
+      <include name="*.jar"/>
+    </fileset>
+    <fileset dir="bin">
+      <include name="*.jar"/>
+    </fileset>
+  </path>
+
+  <target name="clean">
+    <delete dir="build"/>
+    <delete dir="testResults"/>
+  </target>
+
+  <target name="compile">
+    <mkdir dir="build/classes"/>
+
+    <javac sourcepath="" srcdir="src" destdir="build/classes" >
+      <include name="**/*.java"/>
+      <classpath refid="master-classpath"/>
+    </javac>
+  </target>
+
+  <target name="jar">
+    <mkdir dir="build/jar"/>
+    <jar destfile="build/jar/opencv-test.jar" basedir="build/classes">
+      <manifest>
+       <attribute name="Main-Class" value="org.opencv.test.OpenCVTestRunner"/>
+      </manifest>
+    </jar>
+  </target>
+
+  <!-- <target name="run" > -->
+  <!--   <java fork="true" classname="org.opencv.test.OpenCVTestRunner"> -->
+  <!--     <sysproperty key="java.library.path" path="${javaLibraryPath}"/> -->
+  <!--     <classpath refid="master-classpath"/> -->
+  <!--     <classpath> -->
+  <!--         <fileset dir="build/jar"> -->
+  <!--           <include name="*.jar"/> -->
+  <!--         </fileset> -->
+  <!--     </classpath> -->
+  <!--   </java> -->
+  <!-- </target> -->
+
+  <target name="test">
+    <mkdir dir="testResults"/>
+    <junit printsummary="yes" haltonfailure="false">
+      <sysproperty key="java.library.path" path="${javaLibraryPath}"/>
+      <classpath refid="master-classpath"/>
+      <classpath>
+       <pathelement location="build/classes"/>
+      </classpath>
+
+      <formatter type="xml"/>
+
+      <batchtest fork="yes" todir="testResults">
+       <zipfileset src="build/jar/opencv-test.jar" includes="**/*.class" excludes="**/OpenCVTest*">
+        <exclude name="**/*$*.class"/>
+       </zipfileset>
+      </batchtest>
+    </junit>
+  </target>
+
+  <target name="buildAndTest">
+    <antcall target="compile"/>
+    <antcall target="jar"/>
+    <antcall target="test"/>
+  </target>
+</project>
\ No newline at end of file
diff --git a/modules/java/java_test/lib/junit-4.11.jar b/modules/java/java_test/lib/junit-4.11.jar
new file mode 100644 (file)
index 0000000..4d552a6
Binary files /dev/null and b/modules/java/java_test/lib/junit-4.11.jar differ
diff --git a/modules/java/java_test/src/org/opencv/test/OpenCVTestCase.java b/modules/java/java_test/src/org/opencv/test/OpenCVTestCase.java
new file mode 100644 (file)
index 0000000..75e240d
--- /dev/null
@@ -0,0 +1,495 @@
+// TODO: This file is largely a duplicate of the one in android_test.
+
+package org.opencv.test;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.charset.Charset;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.opencv.core.Core;
+import org.opencv.core.CvType;
+import org.opencv.core.Mat;
+import org.opencv.core.Point;
+import org.opencv.core.Point3;
+import org.opencv.core.Rect;
+import org.opencv.core.Scalar;
+import org.opencv.core.Size;
+import org.opencv.features2d.DMatch;
+import org.opencv.features2d.KeyPoint;
+import org.opencv.highgui.Highgui;
+
+public class OpenCVTestCase extends TestCase {
+    //change to 'true' to unblock fail on fail("Not yet implemented")
+    public static final boolean passNYI = true;
+
+    protected static boolean isTestCaseEnabled = true;
+
+    protected static final int matSize = 10;
+    protected static final double EPS = 0.001;
+    protected static final double weakEPS = 0.5;
+
+    private static final String TAG = "OpenCVTestCase";
+
+    protected Mat dst;
+    protected Mat truth;
+
+    protected Scalar colorBlack;
+    protected Scalar colorWhite;
+
+    // Naming notation: <channels info>_[depth]_[dimensions]_value
+    // examples: gray0 - single channel 8U 2d Mat filled with 0
+    // grayRnd - single channel 8U 2d Mat filled with random numbers
+    // gray0_32f_1d
+
+    // TODO: OpenCVTestCase refactorings
+    // - rename matrices
+    // - create methods gray0() and create src1 explicitly
+    // - create some masks
+    // - use truth member everywhere - remove truth from base class - each test
+    // fixture should use own truth filed
+
+    protected Mat gray0;
+    protected Mat gray1;
+    protected Mat gray2;
+    protected Mat gray3;
+    protected Mat gray9;
+    protected Mat gray127;
+    protected Mat gray128;
+    protected Mat gray255;
+    protected Mat grayRnd;
+
+    protected Mat gray_16u_256;
+    protected Mat gray_16s_1024;
+
+    protected Mat gray0_32f;
+    protected Mat gray1_32f;
+    protected Mat gray3_32f;
+    protected Mat gray9_32f;
+    protected Mat gray255_32f;
+    protected Mat grayE_32f;
+    protected Mat grayRnd_32f;
+
+    protected Mat gray0_32f_1d;
+
+    protected Mat gray0_64f;
+    protected Mat gray0_64f_1d;
+
+    protected Mat rgba0;
+    protected Mat rgba128;
+
+    protected Mat rgbLena;
+    protected Mat grayChess;
+
+    protected Mat v1;
+    protected Mat v2;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+       try {
+           System.loadLibrary("opencv_java");  
+       } catch (SecurityException e) {
+           System.out.println(e.toString());
+           System.exit(-1);
+       } catch (UnsatisfiedLinkError e) {
+           System.out.println(e.toString());
+           System.exit(-1);
+       }       
+
+       String pwd;
+       try {
+           pwd = new File(".").getCanonicalPath() + File.separator;
+       } catch (IOException e) {
+           System.out.println(e);
+           return;
+       }
+
+       OpenCVTestRunner.LENA_PATH = pwd + "res/drawable/lena.jpg";
+       OpenCVTestRunner.CHESS_PATH = pwd + "res/drawable/chessboard.jpg";
+       OpenCVTestRunner.LBPCASCADE_FRONTALFACE_PATH = pwd + "res/raw/lbpcascade_frontalface.xml";
+
+       assert(new File(OpenCVTestRunner.LENA_PATH).exists());
+       assert(new File(OpenCVTestRunner.CHESS_PATH).exists());
+       assert(new File(OpenCVTestRunner.LBPCASCADE_FRONTALFACE_PATH).exists());
+
+        dst = new Mat();
+        assertTrue(dst.empty());
+        truth = null;
+
+        colorBlack = new Scalar(0);
+        colorWhite = new Scalar(255, 255, 255);
+
+        gray0 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(0));
+        gray1 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(1));
+        gray2 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(2));
+        gray3 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(3));
+        gray9 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(9));
+        gray127 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(127));
+        gray128 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(128));
+        gray255 = new Mat(matSize, matSize, CvType.CV_8U, new Scalar(255));
+
+        grayRnd = new Mat(matSize, matSize, CvType.CV_8U);
+        Core.randu(grayRnd, 0, 256);
+
+        gray_16u_256 = new Mat(matSize, matSize, CvType.CV_16U, new Scalar(256));
+        gray_16s_1024 = new Mat(matSize, matSize, CvType.CV_16S, new Scalar(1024));
+
+        gray0_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(0.0));
+        gray1_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(1.0));
+        gray3_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(3.0));
+        gray9_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(9.0));
+        gray255_32f = new Mat(matSize, matSize, CvType.CV_32F, new Scalar(255.0));
+        grayE_32f = new Mat(matSize, matSize, CvType.CV_32F);
+        grayE_32f = Mat.eye(matSize, matSize, CvType.CV_32FC1);
+        grayRnd_32f = new Mat(matSize, matSize, CvType.CV_32F);
+        Core.randu(grayRnd_32f, 0, 256);
+
+        gray0_64f = new Mat(matSize, matSize, CvType.CV_64F, new Scalar(0.0));
+
+        gray0_32f_1d = new Mat(1, matSize, CvType.CV_32F, new Scalar(0.0));
+        gray0_64f_1d = new Mat(1, matSize, CvType.CV_64F, new Scalar(0.0));
+
+        rgba0 = new Mat(matSize, matSize, CvType.CV_8UC4, Scalar.all(0));
+        rgba128 = new Mat(matSize, matSize, CvType.CV_8UC4, Scalar.all(128));
+
+        rgbLena = Highgui.imread(OpenCVTestRunner.LENA_PATH);
+        grayChess = Highgui.imread(OpenCVTestRunner.CHESS_PATH, 0);
+
+        v1 = new Mat(1, 3, CvType.CV_32F);
+        v1.put(0, 0, 1.0, 3.0, 2.0);
+        v2 = new Mat(1, 3, CvType.CV_32F);
+        v2.put(0, 0, 2.0, 1.0, 3.0);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+
+        gray0.release();
+        gray1.release();
+        gray2.release();
+        gray3.release();
+        gray9.release();
+        gray127.release();
+        gray128.release();
+        gray255.release();
+        gray_16u_256.release();
+        gray_16s_1024.release();
+        grayRnd.release();
+        gray0_32f.release();
+        gray1_32f.release();
+        gray3_32f.release();
+        gray9_32f.release();
+        gray255_32f.release();
+        grayE_32f.release();
+        grayE_32f.release();
+        grayRnd_32f.release();
+        gray0_32f_1d.release();
+        gray0_64f.release();
+        gray0_64f_1d.release();
+        rgba0.release();
+        rgba128.release();
+        rgbLena.release();
+        grayChess.release();
+        v1.release();
+        v2.release();
+
+        super.tearDown();
+    }
+
+    @Override
+    protected void runTest() throws Throwable {
+        // Do nothing if the precondition does not hold.
+        if (isTestCaseEnabled) {
+            super.runTest();
+        } else {
+            OpenCVTestRunner.Log(TAG + " :: " + "Test case \"" + this.getClass().getName() + "\" disabled!");
+        }
+    }
+
+    protected Mat getMat(int type, double... vals)
+    {
+        return new Mat(matSize, matSize, type, new Scalar(vals));
+    }
+
+    protected Mat makeMask(Mat m, double... vals)
+    {
+        m.submat(0, m.rows(), 0, m.cols() / 2).setTo(new Scalar(vals));
+        return m;
+    }
+
+    public static void fail(String msg) {
+        if(msg == "Not yet implemented" && passNYI)
+            return;
+        TestCase.fail(msg);
+    }
+
+    public static <E extends Number> void assertListEquals(List<E> list1, List<E> list2) {
+        if (list1.size() != list2.size()) {
+            throw new UnsupportedOperationException();
+        }
+
+        if (!list1.isEmpty())
+        {
+            if (list1.get(0) instanceof Float || list1.get(0) instanceof Double)
+                throw new UnsupportedOperationException();
+        }
+
+        for (int i = 0; i < list1.size(); i++)
+            assertEquals(list1.get(i), list2.get(i));
+    }
+
+    public static <E extends Number> void assertListEquals(List<E> list1, List<E> list2, double epsilon) {
+        if (list1.size() != list2.size()) {
+            throw new UnsupportedOperationException();
+        }
+
+        for (int i = 0; i < list1.size(); i++)
+            assertTrue(Math.abs(list1.get(i).doubleValue() - list2.get(i).doubleValue()) <= epsilon);
+    }
+
+    public static <E extends Number> void assertArrayEquals(E[] ar1, E[] ar2, double epsilon) {
+        if (ar1.length != ar2.length) {
+            fail("Arrays have different sizes.");
+        }
+
+        for (int i = 0; i < ar1.length; i++)
+            assertEquals(ar1[i].doubleValue(), ar2[i].doubleValue(), epsilon);
+            //assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
+    }
+
+    public static void assertArrayEquals(double[] ar1, double[] ar2, double epsilon) {
+        if (ar1.length != ar2.length) {
+            fail("Arrays have different sizes.");
+        }
+
+        for (int i = 0; i < ar1.length; i++)
+            assertEquals(ar1[i], ar2[i], epsilon);
+            //assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
+    }
+
+    public static void assertListMatEquals(List<Mat> list1, List<Mat> list2, double epsilon) {
+        if (list1.size() != list2.size()) {
+            throw new UnsupportedOperationException();
+        }
+
+        for (int i = 0; i < list1.size(); i++)
+            assertMatEqual(list1.get(i), list2.get(i), epsilon);
+    }
+
+    public static void assertListPointEquals(List<Point> list1, List<Point> list2, double epsilon) {
+        if (list1.size() != list2.size()) {
+            throw new UnsupportedOperationException();
+        }
+
+        for (int i = 0; i < list1.size(); i++)
+            assertPointEquals(list1.get(i), list2.get(i), epsilon);
+    }
+
+    public static void assertArrayPointsEquals(Point[] vp1, Point[] vp2, double epsilon) {
+        if (vp1.length != vp2.length) {
+            fail("Arrays have different sizes.");
+        }
+
+        for (int i = 0; i < vp1.length; i++)
+            assertPointEquals(vp1[i], vp2[i], epsilon);
+    }
+    public static void assertListPoint3Equals(List<Point3> list1, List<Point3> list2, double epsilon) {
+        if (list1.size() != list2.size()) {
+            throw new UnsupportedOperationException();
+        }
+
+        for (int i = 0; i < list1.size(); i++)
+            assertPoint3Equals(list1.get(i), list2.get(i), epsilon);
+    }
+
+    public static void assertListRectEquals(List<Rect> list1, List<Rect> list2) {
+        if (list1.size() != list2.size()) {
+            throw new UnsupportedOperationException();
+        }
+
+        for (int i = 0; i < list1.size(); i++)
+            assertRectEquals(list1.get(i), list2.get(i));
+    }
+
+    public static void assertRectEquals(Rect expected, Rect actual) {
+        String msg = "expected:<" + expected + "> but was:<" + actual + ">";
+        assertEquals(msg, expected.x, actual.x);
+        assertEquals(msg, expected.y, actual.y);
+        assertEquals(msg, expected.width, actual.width);
+        assertEquals(msg, expected.height, actual.height);
+    }
+
+    public static void assertMatEqual(Mat m1, Mat m2) {
+        compareMats(m1, m2, true);
+    }
+
+    public static void assertMatNotEqual(Mat m1, Mat m2) {
+        compareMats(m1, m2, false);
+    }
+
+    public static void assertMatEqual(Mat expected, Mat actual, double eps) {
+        compareMats(expected, actual, eps, true);
+    }
+
+    public static void assertMatNotEqual(Mat expected, Mat actual, double eps) {
+        compareMats(expected, actual, eps, false);
+    }
+
+    public static void assertKeyPointEqual(KeyPoint expected, KeyPoint actual, double eps) {
+        String msg = "expected:<" + expected + "> but was:<" + actual + ">";
+        assertTrue(msg, Math.hypot(expected.pt.x - actual.pt.x, expected.pt.y - actual.pt.y) < eps);
+        assertTrue(msg, Math.abs(expected.size - actual.size) < eps);
+        assertTrue(msg, Math.abs(expected.angle - actual.angle) < eps);
+        assertTrue(msg, Math.abs(expected.response - actual.response) < eps);
+        assertEquals(msg, expected.octave, actual.octave);
+        assertEquals(msg, expected.class_id, actual.class_id);
+    }
+
+    public static void assertListKeyPointEquals(List<KeyPoint> expected, List<KeyPoint> actual, double epsilon) {
+        assertEquals(expected.size(), actual.size());
+        for (int i = 0; i < expected.size(); i++)
+            assertKeyPointEqual(expected.get(i), actual.get(i), epsilon);
+    }
+
+    public static void assertDMatchEqual(DMatch expected, DMatch actual, double eps) {
+        String msg = "expected:<" + expected + "> but was:<" + actual + ">";
+        assertEquals(msg, expected.queryIdx, actual.queryIdx);
+        assertEquals(msg, expected.trainIdx, actual.trainIdx);
+        assertEquals(msg, expected.imgIdx, actual.imgIdx);
+        assertTrue(msg, Math.abs(expected.distance - actual.distance) < eps);
+    }
+
+    public static void assertScalarEqual(Scalar expected, Scalar actual, double eps) {
+        String msg = "expected:<" + expected + "> but was:<" + actual + ">";
+        assertTrue(msg, Math.abs(expected.val[0] - actual.val[0]) < eps);
+        assertTrue(msg, Math.abs(expected.val[1] - actual.val[1]) < eps);
+        assertTrue(msg, Math.abs(expected.val[2] - actual.val[2]) < eps);
+        assertTrue(msg, Math.abs(expected.val[3] - actual.val[3]) < eps);
+    }
+
+    public static void assertArrayDMatchEquals(DMatch[] expected, DMatch[] actual, double epsilon) {
+        assertEquals(expected.length, actual.length);
+        for (int i = 0; i < expected.length; i++)
+            assertDMatchEqual(expected[i], actual[i], epsilon);
+    }
+
+    public static void assertListDMatchEquals(List<DMatch> expected, List<DMatch> actual, double epsilon) {
+        DMatch expectedArray[] = expected.toArray(new DMatch[0]);
+        DMatch actualArray[]   = actual.toArray(new DMatch[0]);
+        assertArrayDMatchEquals(expectedArray, actualArray, epsilon);
+    }
+
+    public static void assertPointEquals(Point expected, Point actual, double eps) {
+        String msg = "expected:<" + expected + "> but was:<" + actual + ">";
+        assertEquals(msg, expected.x, actual.x, eps);
+        assertEquals(msg, expected.y, actual.y, eps);
+    }
+
+    public static void assertSizeEquals(Size expected, Size actual, double eps) {
+        String msg = "expected:<" + expected + "> but was:<" + actual + ">";
+        assertEquals(msg, expected.width, actual.width, eps);
+        assertEquals(msg, expected.height, actual.height, eps);
+    }
+
+    public static void assertPoint3Equals(Point3 expected, Point3 actual, double eps) {
+        String msg = "expected:<" + expected + "> but was:<" + actual + ">";
+        assertEquals(msg, expected.x, actual.x, eps);
+        assertEquals(msg, expected.y, actual.y, eps);
+        assertEquals(msg, expected.z, actual.z, eps);
+    }
+
+    static private void compareMats(Mat expected, Mat actual, boolean isEqualityMeasured) {
+        if (expected.type() != actual.type() || expected.cols() != actual.cols() || expected.rows() != actual.rows()) {
+            throw new UnsupportedOperationException("Can not compare " + expected + " and " + actual);
+        }
+
+        if (expected.depth() == CvType.CV_32F || expected.depth() == CvType.CV_64F) {
+            if (isEqualityMeasured)
+                throw new UnsupportedOperationException(
+                        "Floating-point Mats must not be checked for exact match. Use assertMatEqual(Mat expected, Mat actual, double eps) instead.");
+            else
+                throw new UnsupportedOperationException(
+                        "Floating-point Mats must not be checked for exact match. Use assertMatNotEqual(Mat expected, Mat actual, double eps) instead.");
+        }
+
+        Mat diff = new Mat();
+        Core.absdiff(expected, actual, diff);
+        Mat reshaped = diff.reshape(1);
+        int mistakes = Core.countNonZero(reshaped);
+
+        reshaped.release();
+        diff.release();
+
+        if (isEqualityMeasured)
+            assertTrue("Mats are different in " + mistakes + " points", 0 == mistakes);
+        else
+            assertFalse("Mats are equal", 0 == mistakes);
+    }
+
+    static private void compareMats(Mat expected, Mat actual, double eps, boolean isEqualityMeasured) {
+        if (expected.type() != actual.type() || expected.cols() != actual.cols() || expected.rows() != actual.rows()) {
+            throw new UnsupportedOperationException("Can not compare " + expected + " and " + actual);
+        }
+
+        Mat diff = new Mat();
+        Core.absdiff(expected, actual, diff);
+        double maxDiff = Core.norm(diff, Core.NORM_INF);
+
+        if (isEqualityMeasured)
+            assertTrue("Max difference between expected and actiual Mats is "+ maxDiff + ", that bigger than " + eps,
+                    Core.checkRange(diff, true, 0.0, eps));
+        else
+            assertFalse("Max difference between expected and actiual Mats is "+ maxDiff + ", that less than " + eps,
+                    Core.checkRange(diff, true, 0.0, eps));
+    }
+
+    protected static String readFile(String path) {
+        FileInputStream stream = null;
+        try {
+            stream = new FileInputStream(new File(path));
+            FileChannel fc = stream.getChannel();
+            MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0,
+                    fc.size());
+            return Charset.defaultCharset().decode(bb).toString();
+        } catch (IOException e) {
+            OpenCVTestRunner.Log("Failed to read file \"" + path
+                    + "\". Exception is thrown: " + e);
+            return null;
+        } finally {
+            if (stream != null)
+                try {
+                    stream.close();
+                } catch (IOException e) {
+                    OpenCVTestRunner.Log("Exception is thrown: " + e);
+                }
+        }
+    }
+
+    protected static void writeFile(String path, String content) {
+        FileOutputStream stream = null;
+        try {
+            stream = new FileOutputStream(new File(path));
+            FileChannel fc = stream.getChannel();
+            fc.write(Charset.defaultCharset().encode(content));
+        } catch (IOException e) {
+            OpenCVTestRunner.Log("Failed to write file \"" + path
+                    + "\". Exception is thrown: " + e);
+        } finally {
+            if (stream != null)
+                try {
+                    stream.close();
+                } catch (IOException e) {
+                    OpenCVTestRunner.Log("Exception is thrown: " + e);
+                }
+        }
+    }
+
+}
diff --git a/modules/java/java_test/src/org/opencv/test/OpenCVTestRunner.java b/modules/java/java_test/src/org/opencv/test/OpenCVTestRunner.java
new file mode 100644 (file)
index 0000000..4d05304
--- /dev/null
@@ -0,0 +1,44 @@
+package org.opencv.test;
+
+import java.io.File;
+import java.io.IOException;
+import junit.framework.Assert;
+
+import org.opencv.core.Mat;
+
+public class OpenCVTestRunner {
+    public static String LENA_PATH = "";
+    public static String CHESS_PATH = "";
+    public static String LBPCASCADE_FRONTALFACE_PATH = "";
+
+    private static String TAG = "opencv_test_java";
+
+
+    public static String getTempFileName(String extension)
+    {
+        if (!extension.startsWith("."))
+            extension = "." + extension;
+        try {
+            File tmp = File.createTempFile("OpenCV", extension);
+            String path = tmp.getAbsolutePath();
+            tmp.delete();
+            return path;
+        } catch (IOException e) {
+            Log("Failed to get temp file name. Exception is thrown: " + e);
+        }
+        return null;
+    }
+
+    static public void Log(String message) {
+        System.out.println(TAG + " :: " +  message);
+    }
+
+    static public void Log(Mat m) {
+        System.out.println(TAG + " :: " + m + "\n " + m.dump());
+    }
+
+    public static String getOutputFileName(String name)
+    {
+       return getTempFileName(name);
+    }
+}