moving into positions to be merged into the mainline

This commit is contained in:
Kohsuke Kawaguchi committed 2012-09-17 14:18:23 -07:00
1 parent e290de6a0e
commit 00b0ebcdf8
9 files changed
-22

No files matched your search

@@ -0,0 +1,197 @@
package ll;
import ll.Attempt2.Direction;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import java.io.IOException;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.SortedMap;
/**
* @author Kohsuke Kawaguchi
*/
public class Attempt2Test extends Assert {
// A=1, B=3, C=5
@Rule
public FakeMapBuilder aBuilder = new FakeMapBuilder();
private FakeMap a;
// empty map
@Rule
public FakeMapBuilder bBuilder = new FakeMapBuilder();
private FakeMap b;
@Rule
public FakeMapBuilder localBuilder = new FakeMapBuilder();
@Before
public void setUp() throws Exception {
a = aBuilder.add(1, "A").add(3, "B").add(5, "C").make();
b = bBuilder.make();
}
@Test
public void lookup() {
a.get(1).asserts(1,"A");
assertNull(a.get(2));
a.get(3).asserts(3,"B");
assertNull(a.get(4));
a.get(5).asserts(5,"C");
assertNull(b.get(1));
assertNull(b.get(3));
assertNull(b.get(5));
}
@Test
public void idempotentLookup() {
for (int i=0; i<5; i++) {
a.get(1).asserts(1,"A");
a.get((Object)1).asserts(1, "A");
}
}
@Test
public void lookupWithBogusKeyType() {
assertNull(a.get(null));
assertNull(a.get("foo"));
assertNull(a.get(this));
}
@Test
public void firstKey() {
assertEquals(1, a.firstKey().intValue());
try {
b.firstKey();
fail();
} catch (NoSuchElementException e) {
// as expected
}
}
@Test
public void lastKey() {
assertEquals(5, a.lastKey().intValue());
try {
b.lastKey();
fail();
} catch (NoSuchElementException e) {
// as expected
}
}
@Test
public void search() {
// searching toward non-existent direction
assertNull(a.search( 99, Direction.ASC));
assertNull(a.search(-99, Direction.DESC));
}
/**
* If load fails, search needs to gracefully handle it
*/
@Test
public void unloadableData() throws IOException {
FakeMap m = localBuilder.add(1, "A").addUnloadable("B").add(5, "C").make();
assertNull(m.search(3,Direction.EXACT));
m.search(3,Direction.DESC).asserts(1,"A");
m.search(3,Direction.ASC ).asserts(5,"C");
}
@Test
public void eagerLoading() throws IOException {
Map.Entry[] b = a.entrySet().toArray(new Map.Entry[3]);
((Build)b[0].getValue()).asserts(1,"A");
((Build)b[1].getValue()).asserts(3,"B");
((Build)b[2].getValue()).asserts(5,"C");
}
@Test
public void fastLookup() throws IOException {
FakeMap a = localBuilder.addBoth(1, "A").addBoth(3, "B").addBoth(5, "C"). make();
a.get(1).asserts(1,"A");
assertNull(a.get(2));
a.get(3).asserts(3,"B");
assertNull(a.get(4));
a.get(5).asserts(5,"C");
}
@Test
public void fastSearch() throws IOException {
FakeMap a = localBuilder.addBoth(1, "A").addBoth(3, "B").addBoth(5, "C").addBoth(7,"D").make();
// we should be using the cache to find the entry efficiently
a.search(6, Direction.ASC).asserts(7,"D");
a.search(2, Direction.DESC).asserts(1, "A");
}
@Test
public void bogusCache() throws IOException {
FakeMap a = localBuilder.addUnloadableCache(1).make();
assertNull(a.get(1));
}
@Test
public void bogusCacheAndHiddenRealData() throws IOException {
FakeMap a = localBuilder.addUnloadableCache(1).add(1,"A").make();
a.get(1).asserts(1, "A");
}
@Test
public void bogusCache2() throws IOException {
FakeMap a = localBuilder.addBogusCache(1,3,"A").make();
assertNull(a.get(1));
a.get(3).asserts(3,"A");
}
@Test
public void incompleteCache() throws IOException {
FakeMapBuilder setup = localBuilder.addBoth(1, "A").add(3, "B").addBoth(5, "C");
// each test uses a fresh map since cache lookup causes additional loads
// to verify the results
// if we just rely on cache,
// it'll pick up 5:C as the first ascending value,
// but we should be then verifying this by loading B, so in the end we should
// find the correct value
setup.make().search(2, Direction.ASC).asserts(3,"B");
setup.make().search(4, Direction.DESC).asserts(3,"B");
// variation of the cache based search where we find the outer-most value via cache
setup.make().search(0, Direction.ASC).asserts(1,"A");
setup.make().search(6, Direction.DESC).asserts(5,"C");
// variation of the cache search where the cache tells us that we are searching
// in the direction that doesn't have any records
assertNull(setup.make().search(0, Direction.DESC));
assertNull(setup.make().search(6, Direction.ASC));
}
@Test
public void fastSubMap() throws Exception {
SortedMap<Integer,Build> m = a.subMap(2, 99);
assertEquals(2, m.size());
Build[] b = m.values().toArray(new Build[2]);
assertEquals(2,b.length);
b[0].asserts(3,"B");
b[1].asserts(5,"C");
}
@Test
public void identity() {
assertTrue(a.equals(a));
assertTrue(!a.equals(b));
a.hashCode();
b.hashCode();
}
}
@@ -0,0 +1,62 @@
package ll;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
/**
* @author Kohsuke Kawaguchi
*/
public class FakeMap extends Attempt2<Build> {
public FakeMap(File dir) {
super(dir);
}
@Override
protected int getNumberOf(Build build) {
return build.n;
}
@Override
protected String getIdOf(Build build) {
return build.id;
}
@Override
protected FilenameFilter createDirectoryFilter() {
return new FilenameFilter() {
public boolean accept(File dir, String name) {
try {
Integer.parseInt(name);
return false;
} catch (NumberFormatException e) {
return true;
}
}
};
}
@Override
protected Build retrieve(File dir) throws IOException {
String n = FileUtils.readFileToString(new File(dir, "n")).trim();
String id = FileUtils.readFileToString(new File(dir, "id")).trim();
return new Build(Integer.parseInt(n),id);
}
}
class Build {
final int n;
final String id;
Build(int n, String id) {
this.n = n;
this.id = id;
}
public void asserts(int n, String id) {
assert this.n==n;
assert this.id.equals(id);
}
}
@@ -0,0 +1,98 @@
package ll;
import org.apache.commons.io.FileUtils;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import java.io.File;
import java.io.IOException;
/**
* Builder for creating a {@link FakeMap}
*
* @author Kohsuke Kawaguchi
*/
public class FakeMapBuilder implements TestRule {
private File dir;
public FakeMapBuilder() {
}
public FakeMapBuilder add(int n, String id) throws IOException {
verifyId(id);
File build = new File(dir,id);
build.mkdir();
FileUtils.write(new File(build, "n"), Integer.toString(n));
FileUtils.write(new File(build,"id"),id);
return this;
}
/**
* Adds a symlink from n to build id.
*
* (in test we should ideally create a symlink, but we fake the test
* by actually making it a directory and staging the same data.)
*/
public FakeMapBuilder addCache(int n, String id) throws IOException {
return addBogusCache(n,n,id);
}
public FakeMapBuilder addBogusCache(int label, int actual, String id) throws IOException {
verifyId(id);
File build = new File(dir,Integer.toString(label));
build.mkdir();
FileUtils.write(new File(build, "n"), Integer.toString(actual));
FileUtils.write(new File(build,"id"),id);
return this;
}
public FakeMapBuilder addBoth(int n, String id) throws IOException {
return add(n,id).addCache(n,id);
}
private void verifyId(String id) {
try {
Integer.parseInt(id);
throw new IllegalMonitorStateException("ID cannot be a number");
} catch (NumberFormatException e) {
// OK
}
}
/**
* Adds a build record under the givn ID but make it unloadable,
* which will cause a failure when a load is attempted on this build ID.
*/
public FakeMapBuilder addUnloadable(String id) throws IOException {
File build = new File(dir,id);
build.mkdir();
return this;
}
public FakeMapBuilder addUnloadableCache(int n) throws IOException {
File build = new File(dir,String.valueOf(n));
build.mkdir();
return this;
}
public FakeMap make() {
return new FakeMap(dir);
}
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
dir = File.createTempFile("lazyload","test");
dir.delete();
dir.mkdirs();
try {
base.evaluate();
} finally {
FileUtils.deleteDirectory(dir);
}
}
};
}
}
@@ -0,0 +1,80 @@
package ll;
import ll.SortedStringList;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
/**
* @author Kohsuke Kawaguchi
*/
public class SortedStringListTest extends Assert {
SortedStringList l = new SortedStringList(new ArrayList<String>(Arrays.asList("B","D","F")));
@Test
public void testCeil() {
assertEquals(0,l.ceil("A"));
assertEquals(0,l.ceil("B"));
assertEquals(1,l.ceil("C"));
assertEquals(1,l.ceil("D"));
assertEquals(2,l.ceil("E"));
assertEquals(2,l.ceil("F"));
assertEquals(3,l.ceil("G"));
}
@Test
public void testFloor() {
assertEquals(-1,l.floor("A"));
assertEquals(0,l.floor("B"));
assertEquals(0,l.floor("C"));
assertEquals(1,l.floor("D"));
assertEquals(1,l.floor("E"));
assertEquals(2,l.floor("F"));
assertEquals(2,l.floor("G"));
}
@Test
public void testLower() {
assertEquals(-1,l.lower("A"));
assertEquals(-1,l.lower("B"));
assertEquals(0,l.lower("C"));
assertEquals(0,l.lower("D"));
assertEquals(1,l.lower("E"));
assertEquals(1,l.lower("F"));
assertEquals(2,l.lower("G"));
}
@Test
public void testHigher() {
assertEquals(0,l.higher("A"));
assertEquals(1,l.higher("B"));
assertEquals(1,l.higher("C"));
assertEquals(2,l.higher("D"));
assertEquals(2,l.higher("E"));
assertEquals(3,l.higher("F"));
assertEquals(3,l.higher("G"));
}
@Test
public void testRange() {
assertTrue(l.isInRange(0));
assertTrue(l.isInRange(1));
assertTrue(l.isInRange(2));
assertFalse(l.isInRange(-1));
assertFalse(l.isInRange(3));
}
@Test
public void remove() {
l.remove("nosuchthing");
assertEquals(3,l.size());
l.remove("B");
assertEquals(2, l.size());
assertEquals("D",l.get(0));
assertEquals("F",l.get(1));
}
}