content: package org.opencv.test;
  
  import java.io.BufferedReader;
  import java.io.File;
  import java.io.FileOutputStream;
  import java.io.FileReader;
  import java.io.IOException;
  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.RotatedRect;
  import org.opencv.core.Scalar;
  import org.opencv.core.Size;
  import org.opencv.core.DMatch;
  import org.opencv.core.KeyPoint;
  import org.opencv.imgcodecs.Imgcodecs;
  
  import android.util.Log;
  import java.lang.reflect.Method;
  import static junit.framework.Assert.assertFalse;
  import static junit.framework.Assert.assertTrue;
  
  public class OpenCVTestCase extends TestCase {
  
      public static class TestSkipException extends RuntimeException {
          public TestSkipException() {}
      }
  
      //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 String XFEATURES2D = "org.opencv.xfeatures2d.";
      protected static final String DEFAULT_FACTORY = "create";
  
      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 gray255_32f_3d;
  
      protected Mat v1;
      protected Mat v2;
  
      @Override
      protected void setUp() throws Exception {
          super.setUp();
  
          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 = Imgcodecs.imread(OpenCVTestRunner.LENA_PATH);
          grayChess = Imgcodecs.imread(OpenCVTestRunner.CHESS_PATH, 0);
  
          gray255_32f_3d = new Mat(new int[]{matSize, matSize, matSize}, CvType.CV_32F, new Scalar(255.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();
          gray255_32f_3d.release();
          v1.release();
          v2.release();
  
          super.tearDown();
      }
  
      @Override
      protected void runTest() throws Throwable {
          // Do nothing if the precondition does not hold.
          if (isTestCaseEnabled) {
              try {
                  super.runTest();
              } catch (TestSkipException ex) {
                  Log.w(TAG, "Test case \"" + this.getClass().getName() + "\" skipped!");
                  assertTrue(true);
              }
          } else {
              Log.e(TAG, "Test case \"" + this.getClass().getName() + "\" disabled!");
          }
      }
  
      public void runBare() throws Throwable {
          Throwable exception = null;
          try {
              setUp();
          } catch (TestSkipException ex) {
              Log.w(TAG, "Test case \"" + this.getClass().getName() + "\" skipped!");
              assertTrue(true);
              return;
          }
          try {
              runTest();
          } catch (Throwable running) {
              exception = running;
          } finally {
              try {
                  tearDown();
              } catch (Throwable tearingDown) {
                  if (exception == null) exception = tearingDown;
              }
          }
          if (exception != null) throw exception;
      }
  
      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 void assertGE(double v1, double v2) {
          assertTrue("Failed: " + v1 + " >= " + v2, v1 >= v2);
      }
  
      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) {
          assertEquals(ar1.length, ar2.length);
  
          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(short[] ar1, short[] ar2) {
          assertEquals(ar1.length, ar2.length);
  
          for (int i = 0; i < ar1.length; i++)
              assertEquals(ar1[i], ar2[i]);
              //assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
      }
  
      public static void assertArrayEquals(double[] ar1, double[] ar2, double epsilon) {
          assertEquals(ar1.length, ar2.length);
  
          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 assertListRotatedRectEquals(List<RotatedRect> list1, List<RotatedRect> list2) {
          if (list1.size() != list2.size()) {
              throw new UnsupportedOperationException();
          }
  
          for (int i = 0; i < list1.size(); i++)
              assertRotatedRectEquals(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 assertRotatedRectEquals(RotatedRect expected, RotatedRect actual) {
          String msg = "expected:<" + expected + "> but was:<" + actual + ">";
          assertEquals(msg, expected.center.x, actual.center.x);
          assertEquals(msg, expected.center.y, actual.center.y);
          assertEquals(msg, expected.size.width, actual.size.width);
          assertEquals(msg, expected.size.height, actual.size.height);
          assertEquals(msg, expected.angle, actual.angle);
      }
  
      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 boolean dimensionsEqual(Mat expected, Mat actual) {
          if (expected.dims() != actual.dims()) {
              return false;
          }
          if (expected.dims() > 2) {
              for (int i = 0; i < expected.dims(); i++) {
                  if (expected.size(i) != actual.size(i)) {
                      return false;
                  }
              }
              return true;
          } else {
              return expected.cols() == actual.cols() && expected.rows() == actual.rows();
          }
      }
  
      static private void compareMats(Mat expected, Mat actual, boolean isEqualityMeasured) {
          if (expected.type() != actual.type() || !dimensionsEqual(expected, actual)) {
              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() || !dimensionsEqual(expected, actual)) {
              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 actual Mats is "+ maxDiff + ", that bigger than " + eps,
                      maxDiff <= eps);
          else
              assertFalse("Max difference between expected and actual Mats is "+ maxDiff + ", that less than " + eps,
                      maxDiff <= eps);
      }
  
      protected static String readFile(String path) {
          try {
          BufferedReader br = new BufferedReader(new FileReader(path));
          String line;
          StringBuffer result = new StringBuffer();
          while ((line = br.readLine()) != null) {
              result.append(line);
              result.append("\n");
          }
          return result.toString();
          } catch (IOException e) {
              OpenCVTestRunner.Log("Failed to read file \"" + path
                      + "\". Exception is thrown: " + e);
              return null;
          }
      }
  
      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);
                  }
          }
      }
  
      protected <T> T createClassInstance(String cname, String factoryName, Class cParams[], Object oValues[]) {
          T instance = null;
  
          assertFalse("Class name should not be empty", "".equals(cname));
  
          String message="";
          try {
              Class algClass = getClassForName(cname);
              Method factory = null;
  
              if(cParams!=null && cParams.length>0) {
                  if(!"".equals(factoryName)) {
                      factory = algClass.getDeclaredMethod(factoryName, cParams);
                      instance = (T) factory.invoke(null, oValues);
                  }
                  else {
                      instance = (T) algClass.getConstructor(cParams).newInstance(oValues);
                  }
              }
              else {
                  if(!"".equals(factoryName)) {
                      factory = algClass.getDeclaredMethod(factoryName);
                      instance = (T) factory.invoke(null);
                  }
                  else {
                      instance = (T) algClass.getConstructor().newInstance();
                  }
              }
          }
          catch(Exception ex) {
              if (cname.startsWith(XFEATURES2D))
              {
                  throw new TestSkipException();
              }
              message = TAG + " :: " + "could not instantiate " + cname + "! Exception: " + ex.getMessage();
          }
  
          assertNotNull(message, instance);
  
          return instance;
      }
  
      protected <T> void setProperty(T instance, String propertyName, String propertyType, Object propertyValue) {
          String message = "";
          try {
              String smethod = "set" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1);
              Method setter = instance.getClass().getMethod(smethod, getClassForName(propertyType));
              setter.invoke(instance, propertyValue);
          }
          catch(Exception ex) {
              message = "Error when setting property [" + propertyName + "]: " + ex.getMessage();
          }
  
          assertTrue(message, "".equals(message));
      }
  
      protected Class getClassForName(String sclass) throws ClassNotFoundException{
          if("int".equals(sclass))
              return Integer.TYPE;
          else if("long".equals(sclass))
              return Long.TYPE;
          else if("double".equals(sclass))
              return Double.TYPE;
          else if("float".equals(sclass))
              return Float.TYPE;
          else if("boolean".equals(sclass))
              return Boolean.TYPE;
          else if("char".equals(sclass))
              return Character.TYPE;
          else if("byte".equals(sclass))
              return Byte.TYPE;
          else if("short".equals(sclass))
              return Short.TYPE;
          else
              return Class.forName(sclass);
  
      }
  
  }
  