blob: 272ba27a890da33dc8f07a790ee844910a282bb9 [file] [log] [blame]
// Copyright 2010-2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package org.mozc.android.inputmethod.japanese.testing;
import static org.easymock.EasyMock.reportMatcher;
import org.mozc.android.inputmethod.japanese.KeycodeConverter.KeyEventInterface;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.protobuf.Message;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.KeyEvent;
import org.easymock.Capture;
import org.easymock.IArgumentMatcher;
import java.util.Arrays;
/**
* This class provides Matcher methods for EasyMock (AndroidMock).
*
*/
public class MozcMatcher {
/**
* Capture for Paint, with deep copy.
*
* Capture holds only reference so it cannot be used for capturing the snapshot.
* This subclass hold copied instance instead.
*/
public static class DeepCopyPaintCapture extends Capture<Paint> {
@Override
public void setValue(Paint value) {
// Don't user Paint(Paint) constructor, which doesn't copy the fields.
// This behavior is fixed new OS but older ones have this issue.
Paint newValue = new Paint();
newValue.set(value);
super.setValue(newValue);
}
}
/**
* Matcher implementation for protobuf's MessageBuilder.
*/
private static class MessageBuilderMatcher implements IArgumentMatcher {
private final Message expected;
MessageBuilderMatcher(Message.Builder builder) {
this.expected = Preconditions.checkNotNull(builder).buildPartial();
}
@Override
public void appendTo(StringBuffer buff) {
buff.append("matchesBuilder(")
.append(expected.toString())
.append(")");
}
@Override
public boolean matches(Object arg) {
if (!(arg instanceof Message.Builder)) {
return false;
}
return expected.equals(Message.Builder.class.cast(arg).buildPartial());
}
}
/**
* Matcher implementation for KeyEvent, which matches action and key code.
*/
private static class KeyEventMatcher implements IArgumentMatcher {
private final int expectedKeyCode;
private final Optional<android.view.KeyEvent> expectedNativeKeyEvent;
KeyEventMatcher(int expectedKeyCode) {
this.expectedKeyCode = expectedKeyCode;
this.expectedNativeKeyEvent = Optional.absent();
}
KeyEventMatcher(android.view.KeyEvent expectedNativeKeyEvent) {
this.expectedKeyCode = android.view.KeyEvent.KEYCODE_UNKNOWN;
this.expectedNativeKeyEvent = Optional.of(expectedNativeKeyEvent);
}
@Override
public void appendTo(StringBuffer sb) {
Preconditions.checkNotNull(sb);
sb.append("matchesKeyEvent(");
sb.appendCodePoint(expectedKeyCode);
sb.append(")");
}
@Override
public boolean matches(Object arg) {
if (!(arg instanceof KeyEventInterface)) {
return false;
}
KeyEventInterface keyEvent = KeyEventInterface.class.cast(arg);
if (expectedNativeKeyEvent.isPresent()) {
Optional<KeyEvent> nativeEvent = keyEvent.getNativeEvent();
return nativeEvent.isPresent() && (nativeEvent.get() == expectedNativeKeyEvent.get());
}
return !keyEvent.getNativeEvent().isPresent() && keyEvent.getKeyCode() == expectedKeyCode;
}
}
/**
* Matcher implementation for Canvas, which matches expected matrix conversion given by
* sourcePoints and targetPoints.
*/
private static class CanvasPointMatcher implements IArgumentMatcher {
private final float[] sourcePoints;
private final float[] targetPoints;
CanvasPointMatcher(float[] sourcePoints, float[] targetPoints) {
Preconditions.checkNotNull(sourcePoints);
Preconditions.checkNotNull(targetPoints);
if (sourcePoints.length != targetPoints.length) {
throw new IllegalArgumentException(
"The length of sourcePoints and one of targetPoints shoudld be same. "
+ "sourcePoints.length: " + sourcePoints.length + ", "
+ "targetPoints.length: " + targetPoints.length);
}
this.sourcePoints = sourcePoints;
this.targetPoints = targetPoints;
}
@Override
public void appendTo(StringBuffer buff) {
buff.append("matchCanvasPoint(")
.append(Arrays.toString(sourcePoints))
.append(", ")
.append(Arrays.toString(targetPoints))
.append(")");
}
@SuppressWarnings("deprecation")
@Override
public boolean matches(Object arg) {
if (!(arg instanceof Canvas)) {
return false;
}
Canvas canvas = Canvas.class.cast(arg);
float[] points = sourcePoints.clone();
canvas.getMatrix().mapPoints(points);
return Arrays.equals(targetPoints, points);
}
}
/**
* Matcher implementation for Optional, which contains a same object.
*/
private static class SameOptionalMatcher<T> implements IArgumentMatcher {
private final T expectedValue;
SameOptionalMatcher(T value) {
this.expectedValue = Preconditions.checkNotNull(value);
}
@Override
public void appendTo(StringBuffer buff) {
buff.append("matchOptional(")
.append(expectedValue)
.append(")");
}
@SuppressWarnings("rawtypes")
@Override
public boolean matches(Object arg) {
if (!(arg instanceof Optional)) {
return false;
}
Optional targetValue = Optional.class.cast(arg);
return expectedValue == targetValue.orNull();
}
}
// Disallow instantiation.
private MozcMatcher() {
}
/**
* Expects a MessageBuilder which contains same information as the given {@code builder}.
*/
public static <T extends Message.Builder> T matchesBuilder(T builder) {
reportMatcher(new MessageBuilderMatcher(builder));
return null;
}
/**
* Expects a {@link KeyEventInterface}, whose key code match the given {@code keyCode}.
*/
public static KeyEventInterface matchesKeyEvent(int keyCode) {
reportMatcher(new KeyEventMatcher(keyCode));
return null;
}
/**
* Expects a {@link KeyEventInterface}, whose key code match the given {@code nativeKeyEvent}.
*/
public static KeyEventInterface matchesKeyEvent(android.view.KeyEvent nativeKeyEvent) {
reportMatcher(new KeyEventMatcher(nativeKeyEvent));
return null;
}
/**
* Expects a {@link Canvas}, whose matrix matches the one given by the pair of
* {@code sourcePoints} and {@code targetPoints}.
*/
public static Canvas matchCanvasPoints(float[] sourcePoints, float[] targetPoints) {
reportMatcher(new CanvasPointMatcher(sourcePoints, targetPoints));
return null;
}
/**
* Expects a {@link Optional}, which contains a same object.
*/
public static <T> Optional<T> sameOptional(T value) {
reportMatcher(new SameOptionalMatcher<T>(value));
return null;
}
}