blob: 9766f584796c642c993d9f74117561bd1f7641bf [file] [log] [blame]
/*
* Copyright 2008 Google Inc.
*
* 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.google.gwt.user.rebind.ui;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.util.UnitTestTreeLogger;
import com.google.gwt.user.client.ui.ImageBundle.Resource;
import com.google.gwt.user.rebind.ui.ImageBundleBuilder.HasRect;
import com.google.gwt.user.rebind.ui.ImageBundleGenerator.JMethodOracle;
import junit.framework.TestCase;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Unit tests for {@link ImageBundleGenerator}. Note that, at present, only a
* small minority of the functionality is really covered. The present tests
* cover the correctness of compile-time diagnostics and the sequence and
* phrasing of error and warning log messages.
*/
public class ImageBundleGeneratorTest extends TestCase {
private static class MockRect implements HasRect {
private final String name;
private final int width, height;
private int left, top;
private boolean hasBeenPositioned;
MockRect(String name, int width, int height) {
this.name = name;
this.width = width;
this.height = height;
}
public int getHeight() {
return height;
}
public int getLeft() {
return left;
}
public String getName() {
return name;
}
public int getTop() {
return top;
}
public int getWidth() {
return width;
}
public boolean hasBeenPositioned() {
return hasBeenPositioned;
}
public void setPosition(int left, int top) {
this.left = left;
this.top = top;
hasBeenPositioned = true;
}
@Override
public String toString() {
return "{" + left + ", " + top + ", " + width + ", " + height + "}";
}
void assertPosition(int left, int top) {
assertTrue(hasBeenPositioned);
assertEquals(left, this.left);
assertEquals(top, this.top);
}
MockRect duplicate() {
final MockRect mr = new MockRect(name, width, height);
mr.hasBeenPositioned = hasBeenPositioned;
mr.left = left;
mr.top = top;
return mr;
}
}
/**
* Ensures that two collections of MockRects are arranged identically.
*
* @param a first collection
* @param b second collection
*/
private static void assertSameArrangement(Collection<MockRect> a,
Collection<MockRect> b) {
final Map<String, MockRect> index = new HashMap<String, MockRect>();
for (MockRect r : a) {
index.put(r.getName(), r);
}
for (MockRect rb : b) {
final MockRect ra = index.get(rb.getName());
rb.assertPosition(ra.getLeft(), ra.getTop());
}
}
@Resource("dunebuggy.gif")
public void duneBuggyInDefaultPackage() {
}
@Resource("a/b/c/dunebuggy.gif")
public void duneBuggyInNonDefaultPackage() {
}
@Resource("io.jpg")
public void ioInSamePackage() {
}
/**
* Validates that presenting the images in different orders does not affect
* the arrangement.
*/
public void testArrangementIsDeterministic() {
List<MockRect> orderA = Arrays.asList(new MockRect("a", 50, 100),
new MockRect("b", 50, 100), new MockRect("c", 100, 50), new MockRect(
"d", 50, 50), new MockRect("e", 50, 50));
List<MockRect> orderB = new ArrayList<MockRect>();
for (int i = orderA.size() - 1; i <= 0; --i) {
orderB.add(orderA.get(i));
}
ImageBundleBuilder.arrangeImages(orderA);
ImageBundleBuilder.arrangeImages(orderB);
assertSameArrangement(orderA, orderB);
}
/**
* Ensures that the basic image packing algorithm is arranging images as
* expected.
*/
public void testBasicImageArrangement() {
// Expected in 2nd column, 2nd in 2nd row.
final MockRect ra = new MockRect("a", 20, 30);
// Expected to be 1st column.
final MockRect rb = new MockRect("b", 10, 100);
// Expected in 2nd column, 1st in 2nd row.
final MockRect rc = new MockRect("c", 20, 40);
// Expected in 2nd column, it is the 1st row.
final MockRect rd = new MockRect("d", 100, 60);
// Expected in 2nd column, 3rd in 2nd row.
final MockRect re = new MockRect("e", 10, 30);
final Collection<MockRect> rects = new ArrayList<MockRect>();
Collections.addAll(rects, ra, rb, rc, rd, re);
ImageBundleBuilder.arrangeImages(rects);
ra.assertPosition(30, 60);
rb.assertPosition(0, 0);
rc.assertPosition(10, 60);
rd.assertPosition(10, 0);
re.assertPosition(50, 60);
}
/**
* This method is to remind the reader that ClassLoader.getResource() doesn't
* want a leading "/" on resource names.
*/
public void testClassLoaderGetResourceHatesLeadingSlash() {
String fqcn = getClass().getCanonicalName();
// This class has a name.
assertNotNull(fqcn);
String thisClassResName = fqcn.replace('.', '/') + ".class";
// It has some slashes.
assertTrue(thisClassResName.indexOf('/') >= 0);
// But it does not start with a slash.
assertFalse(thisClassResName.startsWith("/"));
// The resource is successfully found without a leading slash.
URL url = getClass().getClassLoader().getResource(thisClassResName);
assertNotNull(url);
// It fails to be found found with a leading slash.
url = getClass().getClassLoader().getResource("/" + thisClassResName);
assertNull(url);
}
/**
* Tests that a message is logged and an exception is thrown when a resource
* isn't found after being sought based on the ImageBundle.Resource
* annotation.
*/
@Resource("notfound.png")
public void testResourceNotFoundGivenAnnotation() {
UnitTestTreeLogger.Builder b = new UnitTestTreeLogger.Builder();
b.expectError(
ImageBundleGenerator.msgCannotFindImageFromMetaData("from/metadata/notfound.png"),
null);
UnitTestTreeLogger logger = b.createLogger();
try {
getImageName(logger, new String[0], "nonexistentImg", "from.metadata",
getResourceAnnotation("testResourceNotFoundGivenAnnotation"));
fail("Should have thrown");
} catch (UnableToCompleteException e) {
}
logger.assertCorrectLogEntries();
}
/**
* Tests that a message is logged and an exception is thrown when a resource
* isn't found after being sought based on the method name.
*/
public void testResourceNotFoundGivenNoMetaData() {
UnitTestTreeLogger.Builder b = new UnitTestTreeLogger.Builder();
b.expectError(ImageBundleGenerator.MSG_NO_FILE_BASED_ON_METHOD_NAME, null);
b.expectError("test/nonexistentImg.png", null);
b.expectError("test/nonexistentImg.gif", null);
b.expectError("test/nonexistentImg.jpg", null);
UnitTestTreeLogger logger = b.createLogger();
try {
getImageName(logger, new String[0], "nonexistentImg", "test", null);
fail("Should have thrown");
} catch (UnableToCompleteException e) {
}
logger.assertCorrectLogEntries();
}
/**
* Tests that resources can be found in a variety of ways from an image bundle
* residing in the default package.
*/
public void testResourcesFoundFromImageBundleInDefaultPackage()
throws UnableToCompleteException {
UnitTestTreeLogger.Builder b = new UnitTestTreeLogger.Builder();
UnitTestTreeLogger logger = b.createLogger();
{
// [1] Find an image in the default package using the method name.
String imgName = getImageName(logger, new String[] {
"cabbage.jpg", "lettuce.jpg",}, "cabbage", "", null);
assertEquals("cabbage.jpg", imgName);
}
{
// [2] Find an image in the default package using an annotation.
String imgName = getImageName(logger, new String[] {
"car.png", "dunebuggy.gif",}, "vehicleImage", "",
getResourceAnnotation("duneBuggyInDefaultPackage"));
assertEquals("dunebuggy.gif", imgName);
}
{
// [3] Find an image in a non-default package using an annotation.
String imgName = getImageName(logger, new String[] {
"car.png", "dunebuggy.gif", "a/b/c/dunebuggy.gif",}, "vehicleImage",
"", getResourceAnnotation("duneBuggyInNonDefaultPackage"));
assertEquals("a/b/c/dunebuggy.gif", imgName);
}
logger.assertCorrectLogEntries();
}
/**
* Tests that resources can be found in a variety of ways from an image bundle
* residing in a non-default package.
*/
public void testResourcesFoundFromImageBundleInNonDefaultPackage()
throws UnableToCompleteException {
UnitTestTreeLogger.Builder b = new UnitTestTreeLogger.Builder();
UnitTestTreeLogger logger = b.createLogger();
{
// [1] Find an image in the same package using the method name.
String imgName = getImageName(logger, new String[] {
"x/y/z/europa.png", "x/y/z/io.jpg",}, "io", "x.y.z", null);
assertEquals("x/y/z/io.jpg", imgName);
}
{
// [2] Find an image in the same package using an annotation.
String imgName = getImageName(logger, new String[] {
"x/y/z/europa.png", "x/y/z/io.jpg",}, "moonImage", "x.y.z",
getResourceAnnotation("ioInSamePackage"));
assertEquals("x/y/z/io.jpg", imgName);
}
{
// [3] Find an image in a non-default package using an annotation.
String imgName = getImageName(logger, new String[] {
"car.png", "dunebuggy.gif", "a/b/c/dunebuggy.gif",}, "vehicleImage",
"x.y.z", getResourceAnnotation("duneBuggyInNonDefaultPackage"));
assertEquals("a/b/c/dunebuggy.gif", imgName);
}
logger.assertCorrectLogEntries();
}
private JMethodOracle createJMethodOracle(final String methodName,
final String packageName, final Resource resourceAnnotation) {
return new JMethodOracle() {
public Resource getAnnotation(Class<Resource> clazz) {
return resourceAnnotation;
}
public String getName() {
return methodName;
}
public String getPackageName() {
return packageName;
}
};
}
private String getImageName(UnitTestTreeLogger logger,
final String[] pretendResources, String methodName, String pkgName,
final Resource resAnn) throws UnableToCompleteException {
ImageBundleGenerator ibg = new ImageBundleGenerator(
new ImageBundleGenerator.ResourceLocator() {
private final List<String> resList = Arrays.asList(pretendResources);
public boolean isResourcePresent(String resName) {
return resList.contains(resName);
}
});
JMethodOracle methodOracle = createJMethodOracle(methodName, pkgName,
resAnn);
return ibg.getImageResourceName(logger, methodOracle);
}
private Resource getResourceAnnotation(String methodName) {
Throwable caught = null;
try {
Resource res = getClass().getMethod(methodName, new Class[0]).getAnnotation(
Resource.class);
assertNotNull(res);
return res;
} catch (SecurityException e) {
caught = e;
} catch (NoSuchMethodException e) {
caught = e;
}
fail("Unable to get @Resource annotation from method '" + methodName
+ "' during test due to exception: " + caught.getMessage());
return null;
}
}