// Macro language regression tests
// Requires the ImageJ 1.38 or later

  requires("1.38k");
  runMacro("FilterTester"); // run Michael Schmid's filter tests
  startTime = getTime;
  test = "null";
  roiManagerSelect();
  measure();
  binary();
  logic("Logic");
  math("Math");
  functionCalls("FunctionCall");
  images("Image");
  setBatchMode(true); images("BatchImage"); setBatchMode(false);
  benchmarks("Benchmark");
  analyzeParticles();
  showStatus("Regression tests done ("+d2s((getTime-startTime)/1000,2)+" seconds)");
  beep;
  wait(4000);
  exit();


// Logic tests
function logic(thisTest) {
    test = thisTest;
    if (1>2) fail(1);
    if (2>1) ; else fail(2);
    if (1+2*3!=7||2/3+1!=1+(2/3)) fail(3);
    s = "ImageJ has a very nice macro language";
    if (s=="ImageJ has a very nice macro language2") fail(4);
    if ("ImageJ has a very nice macro language "==s) fail(5);
    a = newArray(1, 2, 3);
    if (a[0]+a[0]!=a[1]) fail(6);
    s = newArray('one', 'two');
    if (s[0]+s[1] != 'onetwo') fail(7);
    if (s[0]>=s[1]) fail(8);
}

// Math tests
// Requires ImageJ 1.34b or later 
function math(thisTest) {
    test = thisTest;
    n = 10;
    if (n++!=10) fail(1);
    if (++n!=12) fail(2);
    if (n--!=12) fail(3);
    if (--n!=10) fail(4);
    a=newArray(0,1,2,3,4,5,6);
    for (i=0; i<a.length; i++)
        sum = sum+=a[i];
    if (sum!=21) fail(10);
    i = 2;
    if (a[i++]!=2) fail(11);
    if (i!=3) fail(12);
    if (a[++i]!=4) fail(13);
    if (i!=4) fail(14);
    if (a[i--]!=4) fail(15);
    if (i!=3) fail(16);
    if (a[--i]!=2) fail(17);
    if (i!=2) fail(18);
    i = 1;
    n = a[i++];
    if (n!=1) fail(19);
    if (i!=2) fail(20);
    n = a[++i];
    if (n!=3) fail(21);
    if (i!=3) fail(21);
}

function functionCalls(thisTest) {
   test = thisTest;
   f1(123);
   f2("aString");
   f3(1+2/3);
   v=1.5; f4(v);
   v = 'hello'; f5(v);
   if (f6()!=-1) fail(6);
   if (2-3!=f6()) fail(6);
   if ("return"!=f7()) fail(7); //**
   a = f8(); if (a.length!=3 || a[1]!=22) fail(8);
   a = newArray(1,2); 
   b = newArray('one','two'); 
   f9(a);
   f10(b);
   f11(a[0]);
   f12(b[1]);
}

function f1(a) {if (a!=123) fail(1);}
function f2(a) {if (a!='aString') fail(2);}
function f3(a) {if (a!=1+2/3) fail(3);}
function f4(a) {if (a!=1.5) fail(4);}
function f5(a) {if (a!='hello') fail(5);}
function f6() {return -1;}
function f7() {return 'return';}
function f8() {a=newArray(11,22,33); return a;}
function f9(b) {if (b.length!=2||b[1]!=2) fail(9);}
function f10(b) {if (b.length!=2||b[0]!='one') fail(10);}
function f11(a) {if (a!=1) fail(11);}
function f12(a) {if (a!='two') fail(12);}


function images(thisTest) {
    test = thisTest;
    n = 10;
    openAtStart = nImages;
    id = newArray(n);
    for (i=0; i<n; i++) {
        size = 20*(i+1)*(i+1);
        run("New...", "name=Image"+i+" type=8-bit fill=Ramp width="+size+" height="+size+" slices=1");
        id[i] = getImageID();
    }
    for (i=0; i<n; i++) {
        title = "Image"+i;
        selectImage(title);
        if (getTitle()!="Image"+i) fail(1);
    }
    for (i=0; i<n; i++) {
        selectImage(id[i]);
        if (getTitle()!="Image"+i) fail(2);
    }
    for (i=0; i<n; i++) {
        title = "Image"+i;
        selectWindow(title);
        if (getTitle()!=title) fail(3);
    }
    for (i=0; i<n; i++) {
        selectImage(id[i]);
        run("Close");
        if (nImages()!=openAtStart + n-i-1) fail(4);
    }
    runRGBSplitTest();
}

function runRGBSplitTest() {
    name = "Test Image";
    run("New...", "name=["+name+"] type=8-bit fill=White width=1000 height=1000 slices=1");
    run("Red");
    run("RGB Color");
    run("RGB Split");
    selectWindow(name+" (red)");
    run("Invert");
    selectWindow(name+" (green)");
    run("Invert");
    run("RGB Merge...", "red=["+name+" (red)] green=["+name+" (green)] blue=["+name+" (blue)]");
    if (toHex(getPixel(0,0))!="ff00ff00") fail(5);
    close();
}

function benchmarks(thisTest) {
    test = thisTest;
    if (sieve()!=1899) fail(1);
    if (ackermann(2,5)!=13) fail(2);
}

function sieve() {
    SIZE = 8190;
    flags = newArray(SIZE+1);
    //start = getTime();
    count=0;
    for(i=0; i<=SIZE; i++) flags[i]=true;
    for (i=0; i<=SIZE; i++) {
       if (flags[i]) {
          prime=i+i+3;
          for(k=i+prime; k<=SIZE; k+=prime)
             flags[k]=false;
          count++;
       }
    }
    //print((getTime-start)/1000);
    return count;
}

function ackermann(m, n) {
    if (m==0)
        return n + 1;
    else if (n==0)
        return ackermann(m-1, 1);
    else
        return ackermann(m-1, ackermann(m, n-1));
}

function fail(n) {
  print("FAIL: "+test+ " test "+n);
}

function analyzeParticles() {
    imageCount = nImages;
    test = "Particle analyzer";
    run("Embryos (42K)");
    run("Set Measurements...", "area mean min centroid redirect=None decimal=3");
    processEmbryos();
    checkResults(1, imageCount+1);
    run("Clear Results");
    setBatchMode(true);
    processEmbryos();
    selectWindow("embryos.jpg");
    close();
    setBatchMode(false);
    checkResults(2, imageCount);
    selectWindow("Results");
    run("Close");
}

function checkResults(n, count) {
    if (nResults!=9 || nImages!= count || getResult("XStart", 0)!=36
    || getResult("Area", 0)!=2697  || getResult("Min", 0)!=31
    || getResult("Max", 0)!=144)
         fail(n);
}

function processEmbryos() {
    run("Duplicate...", "title=embryos-1.jpg");
    run("HSB Stack");
    run("Convert Stack to Images");
    selectWindow("Hue");
    close();
    selectWindow("Saturation");
    close();
    selectWindow("Brightness");
    setAutoThreshold();
    setColor(0);
    fillRect(917, 1078, 507, 84);
    run("Select None");
    run("Analyze Particles...", "size=50 circularity=0.75 show=Masks display exclude clear include record");
    close();
    selectWindow("Brightness");
    close();
}

  function measure() {
    test = "Measure";
    measure2();
    setBatchMode(true);
    test = "Measure (batch)";
    measure2();
    setBatchMode(false);
  }

  // requires ImageJ 1.38k or later
  function measure2() {
     newImage("Test Image", "8-bit White", 500, 500, 1);
     id = getImageID;
     makeOval(20, 20, 229, 219);
     setForegroundColor(0, 0, 0);
     run("Fill");
     makeOval(94, 105, 49, 55);
     setForegroundColor(255, 255, 255);
     run("Fill");
     makeOval(20, 20, 229, 219);
     run("Set Scale...", "distance=1 known=1 pixel=1 unit=");
     run("Set Measurements...", "area fit circularity feret's redirect=None decimal=5");
     run("Clear Results");
     run("Measure");
     area = getResult("Area",0);
     feret = getResult("Feret",0);
     circularity = getResult("Circ.",0);
     minor = getResult("Minor",0);
     if (area!=39395) fail(1);
     if (feret!=229) fail(2);
     if (abs(circularity-0.9997)>0.0001) fail(3);
     if (abs(minor-219.0134)>0.0001) fail(4);
     run("Duplicate...", "title=temp");
     run("Restore Selection");
     setAutoThreshold();
     run("Convert to Mask");
     run("Restore Selection");
     getHistogram(values, counts, 256);
     if (counts[255]!=2115) fail(5);
     close;
     selectImage(id);
     close;
     selectWindow("Results");
     run("Close");
  }

  function binary() {
    test = "Binary";
    binary2();
    setBatchMode(true);
    test = "Binary (batch)";
    binary2();
    setBatchMode(false);
  }

  function binary2() {
     run("Options...", "iterations=1 count=1 ");
     run("Blobs (25K)");
     run("Convert to Mask");
     getHistogram(0, counts, 256);
     if (counts[255]!= 22243) fail(1);
     run("Erode");
     getHistogram(0, counts, 256);
     if (counts[255]!= 17256) fail(2);
     run("Undo");
     run("Close-");
     getHistogram(0, counts, 256);
     if (counts[255]!= 21900) fail(3);
     run("Undo");
     run("Open");
     getHistogram(0, counts, 256);
     if (counts[255]!= 22148) fail(4);
     run("Undo");
     run("Skeletonize");
     getHistogram(0, counts, 256);
     if (counts[255]!= 674) fail(5);
     run("Undo");
     run("Options...", "iterations=4 count=4");
     run("Open");
     getHistogram(0, counts, 256);
     if (counts[255]!= 19196) fail(6);
     run("Options...", "iterations=1 count=1 ");
     close;
  }

 
function roiManagerSelect() {
   test = "Roi Manager";
   setBatchMode(true);
   newImage("Untitled", "8-bit", 2000, 2000, 1);
   width = getWidth();
   height = getHeight();
   if (roiManager("count")>0) roiManager("reset");
   n = 250;
   x = newArray(n);
   y = newArray(n);
   w = newArray(n);
   h = newArray(n);
   for (i=0; i<n; i++) {
       w[i] = random()*width/2+1;
       h[i] = random()*width/2+1;
       x[i] = random()*width-w/2;
       y[i] = random()*height-h/2;
       makeRectangle(x[i], y[i], w[i], h[i]);
       roiManager("add");
   }
   n = roiManager("count");
   for (i=0; i<n; i++) {
       roiManager("select", i);
       getSelectionBounds(x2, y2, w2, h2);
       if (x2!=floor(x[i]) || y2!=floor(y[i]) || w2!=floor(w[i]) || h2!=floor(h[i]))
           fail(1);
   }
   close;
   setBatchMode(false);
   if (isOpen("ROI Manager")) {
      selectWindow("ROI Manager");
      run("Close");
   }
}




