- Add in device "drag" command to simulate a finger moving across the touch screen
- Add in some pixel operation on MonkeyImage to scripts can do pixel level tests and comparisons.
- Fix up the help command to no longer loop forever.
- Start MonkeyRunner in interactive mode if no script file is specified.
Change-Id: Ifd2655d3291dcc9dc355d4c2efa9019dc38bee5d
}
/**
+ * Get a python floating point value from an ArgParser.
+ *
+ * @param ap the ArgParser to get the value from.
+ * @param position the position in the parser
+ * @param defaultValue the default value to return if the arg isn't specified.
+ * @return the double value
+ */
+ public static double getFloat(ArgParser ap, int position, double defaultValue) {
+ PyObject arg = ap.getPyObject(position, new PyFloat(defaultValue));
+
+ if (Py.isInstance(arg, PyFloat.TYPE)) {
+ return ((PyFloat) arg).asDouble();
+ }
+ if (Py.isInstance(arg, PyInteger.TYPE)) {
+ return ((PyInteger) arg).asDouble();
+ }
+ throw Py.TypeError("Unable to parse argument: " + position);
+ }
+
+ /**
* Get a list of arguments from an ArgParser.
*
* @param ap the ArgParser
import com.android.monkeyrunner.doc.MonkeyRunnerExported;
import org.python.core.ArgParser;
+import org.python.core.Py;
import org.python.core.PyDictionary;
import org.python.core.PyException;
import org.python.core.PyObject;
+import org.python.core.PyTuple;
import java.util.Collection;
import java.util.Collections;
touch(x, y, type);
}
+ @MonkeyRunnerExported(doc = "Simulate a drag on the screen.",
+ args = { "start", "end", "duration", "steps"},
+ argDocs = { "The starting point for the drag (a tuple of x,y)",
+ "The end point for the drag (a tuple of x,y)",
+ "How long (in seconds) should the drag take (default is 1.0 seconds)",
+ "The number of steps to take when interpolating points. (default is 10)"})
+ public void drag(PyObject[] args, String[] kws) {
+ ArgParser ap = JythonUtils.createArgParser(args, kws);
+ Preconditions.checkNotNull(ap);
+
+ PyObject startObject = ap.getPyObject(0);
+ if (!(startObject instanceof PyTuple)) {
+ throw Py.TypeError("Agrument 0 is not a tuple");
+ }
+ PyObject endObject = ap.getPyObject(1);
+ if (!(endObject instanceof PyTuple)) {
+ throw Py.TypeError("Agrument 1 is not a tuple");
+ }
+
+ PyTuple start = (PyTuple) startObject;
+ PyTuple end = (PyTuple) endObject;
+
+ int startx = (Integer) start.__getitem__(0).__tojava__(Integer.class);
+ int starty = (Integer) start.__getitem__(1).__tojava__(Integer.class);
+ int endx = (Integer) end.__getitem__(0).__tojava__(Integer.class);
+ int endy = (Integer) end.__getitem__(1).__tojava__(Integer.class);
+
+ double seconds = JythonUtils.getFloat(ap, 2, 1.0);
+ long ms = (long) (seconds * 1000.0);
+
+ int steps = ap.getInt(3, 10);
+
+ drag(startx, starty, endx, endy, steps, ms);
+ }
+
@MonkeyRunnerExported(doc = "Send a key press event to the specified button",
args = { "name", "type" },
argDocs = { "the name of the key to press", "the type of touch event to send"})
return JythonUtils.convertMapToDict(result);
}
+ @MonkeyRunnerExported(doc = "Wake up the screen on the device")
public void wake(PyObject[] args, String[] kws) {
ArgParser ap = JythonUtils.createArgParser(args, kws);
Preconditions.checkNotNull(ap);
protected abstract String getSystemProperty(String key);
protected abstract void touch(int x, int y, TouchPressType type);
protected abstract void press(String keyName, TouchPressType type);
+ protected abstract void drag(int startx, int starty, int endx, int endy, int steps, long ms);
protected abstract void type(String string);
protected abstract String shell(String cmd);
protected abstract boolean installPackage(String path);
import com.android.monkeyrunner.doc.MonkeyRunnerExported;
import org.python.core.ArgParser;
+import org.python.core.PyInteger;
import org.python.core.PyObject;
+import org.python.core.PyTuple;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
+import java.lang.ref.WeakReference;
import java.util.Iterator;
import javax.imageio.ImageIO;
* Jython object to encapsulate images that have been taken.
*/
public abstract class MonkeyImage {
+ /**
+ * Convert the MonkeyImage into a BufferedImage.
+ *
+ * @return a BufferedImage for this MonkeyImage.
+ */
public abstract BufferedImage createBufferedImage();
+ // Cache the BufferedImage so we don't have to generate it every time.
+ private WeakReference<BufferedImage> cachedBufferedImage = null;
+
+ /**
+ * Utility method to handle getting the BufferedImage and managing the cache.
+ *
+ * @return the BufferedImage for this image.
+ */
+ private BufferedImage getBufferedImage() {
+ // Check the cache first
+ if (cachedBufferedImage != null) {
+ BufferedImage img = cachedBufferedImage.get();
+ if (img != null) {
+ return img;
+ }
+ }
+
+ // Not in the cache, so create it and cache it.
+ BufferedImage img = createBufferedImage();
+ cachedBufferedImage = new WeakReference<BufferedImage>(img);
+ return img;
+ }
+
+ @MonkeyRunnerExported(doc = "Encode the image into a format and return the bytes.",
+ args = {"format"},
+ argDocs = { "The (optional) format in which to encode the image (PNG for example)" },
+ returns = "A String containing the bytes.")
+ public byte[] convertToBytes(PyObject[] args, String[] kws) {
+ ArgParser ap = JythonUtils.createArgParser(args, kws);
+ Preconditions.checkNotNull(ap);
+
+ String format = ap.getString(0, "png");
+
+ BufferedImage argb = convertSnapshot();
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ try {
+ ImageIO.write(argb, format, os);
+ } catch (IOException e) {
+ return new byte[0];
+ }
+ return os.toByteArray();
+ }
+
@MonkeyRunnerExported(doc = "Write out the file to the specified location. If no " +
"format is specified, this function tries to guess at the output format " +
"depending on the file extension given. If unable to determine, it uses PNG.",
args = {"path", "format"},
- argDocs = {"Where to write out the file"},
+ argDocs = {"Where to write out the file",
+ "The format in which to encode the image (PNG for example)"},
returns = "True if writing succeeded.")
public boolean writeToFile(PyObject[] args, String[] kws) {
ArgParser ap = JythonUtils.createArgParser(args, kws);
return writeToFile(path, "png");
}
ImageWriter writer = writers.next();
- BufferedImage image = createBufferedImage();
+ BufferedImage image = getBufferedImage();
try {
File f = new File(path);
f.delete();
return true;
}
- public boolean writeToFile(String path, String format) {
- BufferedImage image = createBufferedImage();
+ @MonkeyRunnerExported(doc = "Get a single ARGB pixel from the image",
+ args = { "x", "y" },
+ argDocs = { "the x offset of the pixel", "the y offset of the pixel" },
+ returns = "A tuple of (A, R, G, B) for the pixel")
+ public PyObject getRawPixel(PyObject[] args, String[] kws) {
+ ArgParser ap = JythonUtils.createArgParser(args, kws);
+ Preconditions.checkNotNull(ap);
+
+ int x = ap.getInt(0);
+ int y = ap.getInt(1);
+ int pixel = getPixel(x, y);
+ PyInteger a = new PyInteger((pixel & 0xFF000000) >> 24);
+ PyInteger r = new PyInteger((pixel & 0x00FF0000) >> 16);
+ PyInteger g = new PyInteger((pixel & 0x0000FF00) >> 8);
+ PyInteger b = new PyInteger((pixel & 0x000000FF) >> 0);
+ return new PyTuple(a, r, g ,b);
+ }
+
+ @MonkeyRunnerExported(doc = "Get a single ARGB pixel from the image",
+ args = { "x", "y" },
+ argDocs = { "the x offset of the pixel", "the y offset of the pixel" },
+ returns = "An integer for the ARGB pixel")
+ public int getRawPixelInt(PyObject[] args, String[] kws) {
+ ArgParser ap = JythonUtils.createArgParser(args, kws);
+ Preconditions.checkNotNull(ap);
+
+ int x = ap.getInt(0);
+ int y = ap.getInt(1);
+ return getPixel(x, y);
+ }
+
+ private int getPixel(int x, int y) {
+ BufferedImage image = getBufferedImage();
+ return image.getRGB(x, y);
+ }
+
+ private BufferedImage convertSnapshot() {
+ BufferedImage image = getBufferedImage();
// Convert the image to ARGB so ImageIO writes it out nicely
BufferedImage argb = new BufferedImage(image.getWidth(), image.getHeight(),
Graphics g = argb.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
+ return argb;
+ }
+
+ public boolean writeToFile(String path, String format) {
+ BufferedImage argb = convertSnapshot();
try {
ImageIO.write(argb, format, new File(path));
}
return true;
}
-}
+
+ @MonkeyRunnerExported(doc = "Compare this image to the other image.",
+ args = {"other"},
+ argDocs = {"The other image."},
+ returns = "True if they are the same image.")
+ public boolean sameAs(PyObject[] args, String[] kws) {
+ ArgParser ap = JythonUtils.createArgParser(args, kws);
+ Preconditions.checkNotNull(ap);
+
+ PyObject otherObject = ap.getPyObject(0);
+ MonkeyImage other = (MonkeyImage) otherObject.__tojava__(MonkeyImage.class);
+
+ BufferedImage otherImage = other.getBufferedImage();
+ BufferedImage myImage = getBufferedImage();
+
+ // Easy size check
+ if (otherImage.getWidth() != myImage.getWidth()) {
+ return false;
+ }
+ if (otherImage.getHeight() != myImage.getHeight()) {
+ return false;
+ }
+
+ int[] otherPixel = new int[1];
+ int[] myPixel = new int[1];
+
+ // Now, go through pixel-by-pixel and check that the images are the same;
+ for (int y = 0; y < myImage.getHeight(); y++) {
+ for (int x = 0; x < myImage.getWidth(); x++) {
+ if (myImage.getRGB(x, y) != otherImage.getRGB(x, y)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static class BufferedImageMonkeyImage extends MonkeyImage {
+ private final BufferedImage image;
+
+ public BufferedImageMonkeyImage(BufferedImage image) {
+ this.image = image;
+ }
+
+ @Override
+ public BufferedImage createBufferedImage() {
+ return image;
+ }
+
+ }
+
+ @MonkeyRunnerExported(doc = "Get a sub-image of this image.",
+ args = {"rect"},
+ argDocs = {"A Tuple of (x, y, w, h) representing the area of the image to extract."},
+ returns = "The newly extracted image.")
+ public MonkeyImage getSubImage(PyObject[] args, String[] kws) {
+ ArgParser ap = JythonUtils.createArgParser(args, kws);
+ Preconditions.checkNotNull(ap);
+
+ PyTuple rect = (PyTuple) ap.getPyObjectByType(0, PyTuple.TYPE);
+ int x = rect.__getitem__(0).asInt();
+ int y = rect.__getitem__(1).asInt();
+ int w = rect.__getitem__(2).asInt();
+ int h = rect.__getitem__(3).asInt();
+
+ BufferedImage image = getBufferedImage();
+ return new BufferedImageMonkeyImage(image.getSubimage(x, y, w, h));
+ }
+}
\ No newline at end of file
}
/**
+ * Send a touch move event at the specified location.
+ *
+ * @param x the x coordinate of where to click
+ * @param y the y coordinate of where to click
+ * @return success or not
+ * @throws IOException on error communicating with the device
+ */
+ public boolean touchMove(int x, int y) throws IOException {
+ return sendMonkeyEvent("touch move " + x + " " + y);
+ }
+
+ /**
* Send a touch (down and then up) event at the specified location.
*
* @param x the x coordinate of where to click
// Containing classes
for (Class<?> toAdd : clz.getClasses()) {
- newClasses.add(toAdd);
+ if (haventSeen.apply(toAdd)) {
+ newClasses.add(toAdd);
+ }
}
}
ImmutableList.Builder<File> pluginListBuilder = ImmutableList.builder();
ImmutableList.Builder<String> argumentBuilder = ImmutableList.builder();
- do {
+ while (index < args.length) {
String argument = args[index++];
if ("-s".equals(argument)) {
argumentBuilder.add(argument);
}
}
- } while (index < args.length);
-
- if (scriptFile == null) {
- printUsage("Missing required parameter");
- return null;
- }
+ };
return new MonkeyRunnerOptions(hostname, port, scriptFile, backend,
pluginListBuilder.build(), argumentBuilder.build());
private int run() {
MonkeyRunner.setBackend(backend);
Map<String, Predicate<PythonInterpreter>> plugins = handlePlugins();
- int error = ScriptRunner.run(options.getScriptFile().getAbsolutePath(),
- options.getArguments(), plugins);
- backend.shutdown();
- MonkeyRunner.setBackend(null);
- return error;
+ if (options.getScriptFile() == null) {
+ ScriptRunner.console();
+ return 0;
+ } else {
+ int error = ScriptRunner.run(options.getScriptFile().getAbsolutePath(),
+ options.getArguments(), plugins);
+ backend.shutdown();
+ MonkeyRunner.setBackend(null);
+ return error;
+ }
}
private Predicate<PythonInterpreter> handlePlugin(File f) {
import org.python.util.PythonInterpreter;
import java.io.File;
-import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
}
/**
- * Create and run a console using a new python interpreter for the test
- * associated with this instance.
+ * Start an interactive python interpreter.
*/
- public void console() throws IOException {
+ public static void console() {
initPython();
InteractiveConsole python = new InteractiveConsole();
- initInterpreter(python, scope, variable);
python.interact();
}
-
- /**
- * Start an interactive python interpreter using the specified set of local
- * variables. Use this to interrupt a running test script with a prompt:
- *
- * @param locals
- */
- public static void console(PyObject locals) {
- initPython();
- InteractiveConsole python = new InteractiveConsole(locals);
- python.interact();
- }
-
- /**
- * Initialize a python interpreter.
- *
- * @param python
- * @param scope
- * @throws IOException
- */
- public static void initInterpreter(PythonInterpreter python, Object scope, String variable)
- throws IOException {
- // Store the current test case as the this variable
- python.set(variable, scope);
- }
}
import com.android.monkeyrunner.MonkeyDevice;
import com.android.monkeyrunner.MonkeyImage;
import com.android.monkeyrunner.MonkeyManager;
+import com.android.monkeyrunner.adb.LinearInterpolator.Point;
import java.io.IOException;
import java.net.InetAddress;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
-import java.util.regex.Pattern;
import javax.annotation.Nullable;
}
return map;
}
+
+ @Override
+ protected void drag(int startx, int starty, int endx, int endy, int steps, long ms) {
+ final long iterationTime = ms / steps;
+
+ LinearInterpolator lerp = new LinearInterpolator(steps);
+ LinearInterpolator.Point start = new LinearInterpolator.Point(startx, starty);
+ LinearInterpolator.Point end = new LinearInterpolator.Point(endx, endy);
+ lerp.interpolate(start, end, new LinearInterpolator.Callback() {
+ @Override
+ public void step(Point point) {
+ try {
+ manager.touchMove(point.getX(), point.getY());
+ } catch (IOException e) {
+ LOG.log(Level.SEVERE, "Error sending drag start event", e);
+ }
+
+ try {
+ Thread.sleep(iterationTime);
+ } catch (InterruptedException e) {
+ LOG.log(Level.SEVERE, "Error sleeping", e);
+ }
+ }
+
+ @Override
+ public void start(Point point) {
+ try {
+ manager.touchDown(point.getX(), point.getY());
+ } catch (IOException e) {
+ LOG.log(Level.SEVERE, "Error sending drag start event", e);
+ }
+
+ try {
+ Thread.sleep(iterationTime);
+ } catch (InterruptedException e) {
+ LOG.log(Level.SEVERE, "Error sleeping", e);
+ }
+ }
+
+ @Override
+ public void end(Point point) {
+ try {
+ manager.touchUp(point.getX(), point.getY());
+ } catch (IOException e) {
+ LOG.log(Level.SEVERE, "Error sending drag end event", e);
+ }
+ }
+ });
+ }
}
--- /dev/null
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.monkeyrunner.adb;
+
+
+
+/**
+ * Linear Interpolation class.
+ */
+public class LinearInterpolator {
+ private final int steps;
+
+ /**
+ * Use our own Point class so we don't pull in java.awt.* just for this simple class.
+ */
+ public static class Point {
+ private final int x;
+ private final int y;
+
+ public Point(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder().
+ append("(").
+ append(x).
+ append(",").
+ append(y).
+ append(")").toString();
+ }
+
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Point) {
+ Point that = (Point) obj;
+ return this.x == that.x && this.y == that.y;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0x43125315 + x + y;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getY() {
+ return y;
+ }
+ }
+
+ /**
+ * Callback interface to recieve interpolated points.
+ */
+ public interface Callback {
+ /**
+ * Called once to inform of the start point.
+ */
+ void start(Point point);
+ /**
+ * Called once to inform of the end point.
+ */
+ void end(Point point);
+ /**
+ * Called at every step in-between start and end.
+ */
+ void step(Point point);
+ }
+
+ /**
+ * Create a new linear Interpolator.
+ *
+ * @param steps How many steps should be in a single run. This counts the intervals
+ * in-between points, so the actual number of points generated will be steps + 1.
+ */
+ public LinearInterpolator(int steps) {
+ this.steps = steps;
+ }
+
+ // Copied from android.util.MathUtils since we couldn't link it in on the host.
+ private static float lerp(float start, float stop, float amount) {
+ return start + (stop - start) * amount;
+ }
+
+ /**
+ * Calculate the interpolated points.
+ *
+ * @param start The starting point
+ * @param end The ending point
+ * @param callback the callback to call with each calculated points.
+ */
+ public void interpolate(Point start, Point end, Callback callback) {
+ int xDistance = Math.abs(end.getX() - start.getX());
+ int yDistance = Math.abs(end.getY() - start.getY());
+ float amount = (float) (1.0 / steps);
+
+
+ callback.start(start);
+ for (int i = 1; i < steps; i++) {
+ float newX = lerp(start.getX(), end.getX(), amount * i);
+ float newY = lerp(start.getY(), end.getY(), amount * i);
+
+ callback.step(new Point(Math.round(newX), Math.round(newY)));
+ }
+ // Generate final point
+ callback.end(end);
+ }
+}
*/
package com.android.monkeyrunner;
+import com.android.monkeyrunner.adb.LinearInterpolatorTest;
+
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestResult;
public static void main(String args[]) {
TestRunner tr = new TestRunner();
TestResult result = tr.doRun(AllTests.suite(ImageUtilsTest.class, JythonUtilsTest.class,
- MonkeyRunnerOptionsTest.class));
+ MonkeyRunnerOptionsTest.class, LinearInterpolatorTest.class));
if (result.wasSuccessful()) {
System.exit(0);
} else {
--- /dev/null
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.monkeyrunner.adb;
+
+import com.google.common.collect.Lists;
+
+import com.android.monkeyrunner.adb.LinearInterpolator.Point;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+
+/**
+ * Unit tests for the LinerInterpolator class.S
+ */
+public class LinearInterpolatorTest extends TestCase {
+ private static class Collector implements LinearInterpolator.Callback {
+ private final List<LinearInterpolator.Point> points = Lists.newArrayList();
+
+ public List<LinearInterpolator.Point> getPoints() {
+ return points;
+ }
+
+ @Override
+ public void end(Point input) {
+ points.add(input);
+ }
+
+ @Override
+ public void start(Point input) {
+ points.add(input);
+ }
+
+ @Override
+ public void step(Point input) {
+ points.add(input);
+ }
+ }
+
+ List<Integer> STEP_POINTS = Lists.newArrayList(0, 100, 200, 300, 400, 500, 600, 700, 800, 900,
+ 1000);
+ List<Integer> REVERSE_STEP_POINTS = Lists.newArrayList(1000, 900, 800, 700, 600, 500, 400, 300,
+ 200, 100, 0);
+
+ public void testLerpRight() {
+ LinearInterpolator lerp = new LinearInterpolator(10);
+ Collector collector = new Collector();
+ lerp.interpolate(new LinearInterpolator.Point(0, 100),
+ new LinearInterpolator.Point(1000, 100),
+ collector);
+
+ List<LinearInterpolator.Point> points = collector.getPoints();
+ assertEquals(11, points.size());
+ for (int x = 0; x < points.size(); x++) {
+ assertEquals(new Point(STEP_POINTS.get(x), 100), points.get(x));
+ }
+ }
+
+ public void testLerpLeft() {
+ LinearInterpolator lerp = new LinearInterpolator(10);
+ Collector collector = new Collector();
+ lerp.interpolate(new LinearInterpolator.Point(1000, 100),
+ new LinearInterpolator.Point(0, 100),
+ collector);
+
+ List<LinearInterpolator.Point> points = collector.getPoints();
+ assertEquals(11, points.size());
+ for (int x = 0; x < points.size(); x++) {
+ assertEquals(new Point(REVERSE_STEP_POINTS.get(x), 100), points.get(x));
+ }
+ }
+
+ public void testLerpUp() {
+ LinearInterpolator lerp = new LinearInterpolator(10);
+ Collector collector = new Collector();
+ lerp.interpolate(new LinearInterpolator.Point(100, 1000),
+ new LinearInterpolator.Point(100, 0),
+ collector);
+
+ List<LinearInterpolator.Point> points = collector.getPoints();
+ assertEquals(11, points.size());
+ for (int x = 0; x < points.size(); x++) {
+ assertEquals(new Point(100, REVERSE_STEP_POINTS.get(x)), points.get(x));
+ }
+ }
+
+ public void testLerpDown() {
+ LinearInterpolator lerp = new LinearInterpolator(10);
+ Collector collector = new Collector();
+ lerp.interpolate(new LinearInterpolator.Point(100, 0),
+ new LinearInterpolator.Point(100, 1000),
+ collector);
+
+ List<LinearInterpolator.Point> points = collector.getPoints();
+ assertEquals(11, points.size());
+ for (int x = 0; x < points.size(); x++) {
+ assertEquals(new Point(100, STEP_POINTS.get(x)), points.get(x));
+ }
+ }
+
+ public void testLerpNW() {
+ LinearInterpolator lerp = new LinearInterpolator(10);
+ Collector collector = new Collector();
+ lerp.interpolate(new LinearInterpolator.Point(0, 0),
+ new LinearInterpolator.Point(1000, 1000),
+ collector);
+
+ List<LinearInterpolator.Point> points = collector.getPoints();
+ assertEquals(11, points.size());
+ for (int x = 0; x < points.size(); x++) {
+ assertEquals(new Point(STEP_POINTS.get(x), STEP_POINTS.get(x)), points.get(x));
+ }
+ }
+
+ public void testLerpNE() {
+ LinearInterpolator lerp = new LinearInterpolator(10);
+ Collector collector = new Collector();
+ lerp.interpolate(new LinearInterpolator.Point(1000, 1000),
+ new LinearInterpolator.Point(0, 0),
+ collector);
+
+ List<LinearInterpolator.Point> points = collector.getPoints();
+ assertEquals(11, points.size());
+ for (int x = 0; x < points.size(); x++) {
+ assertEquals(new Point(REVERSE_STEP_POINTS.get(x), REVERSE_STEP_POINTS.get(x)), points.get(x));
+ }
+ }
+}