Hi David, Sean,
I have made little changes to make understanding little easier, see
attachment...
-Ulf
Am 28.03.2012 07:29, schrieb David Holmes:
Hi Ulf,
I understand your point about ensuring we test AbstractCollection.toArray but I find this revised
test much harder to understand.
Also in the name setPseudoConcurrentSizeCourse the word "Course" doesn't fit. I'm not sure what
you were meaning here? Perhaps just modifySize or emulateConcurrentSizeChange ?
Thanks,
David
import java.util.*;
/**
*
* @author Ulf Zibis
*/
public class TestCollection<E> extends AbstractCollection<E> {
private static final int[] FIXED_SIZE = new int[1];
private final E[] elements;
private int[] sizes;
private int nextSize;
public TestCollection(E[] elements) {
this.elements = elements;
FIXED_SIZE[0] = elements.length;
setPseudoConcurrentChronologicalSizeSequence(FIXED_SIZE);
}
void setPseudoConcurrentChronologicalSizeSequence(int... sizes) {
this.sizes = sizes;
nextSize = 0;
}
/** can change collection's size after each invocation */
@Override
public int size() {
return sizes[nextSize == sizes.length-1 ? nextSize : nextSize++];
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
int pos = 0;
public boolean hasNext() {
return pos < sizes[nextSize];
}
public E next() {
return elements[pos++];
}
public void remove() {
throw new UnsupportedOperationException("Not supported yet.");
}
};
}
}
import java.util.*;
/**
* @test
* @summary check result, especially if the collection concurrently changes size
* @bug 7121314
* @author Ulf Zibis
*/
public class ToArray extends InfraStructure {
static final Object[] OBJECTS = { new Object(), new Object(), new Object()
};
static final TestCollection<?> CANDIDATE = new
TestCollection<Object>(OBJECTS);
static final int CAP = OBJECTS.length; // capacity of the CANDIDATE
static final int LAST = CAP - 1; // last possible array index
Object[] a;
Object[] res;
int last() { return a.length - 1; }
@Override
protected void test() throws Throwable {
// Check array type conversion
res = new TestCollection(new Object[]{"1", "2"}).toArray(new String[0]);
check(res instanceof String[]);
check(res.length == 2);
check(res[1] == "2");
// Check incompatible type of target array
try {
res = CANDIDATE.toArray(new String[CAP]);
check(false);
} catch (Throwable t) {
check(t instanceof ArrayStoreException);
}
// Check more elements than a.length
a = new Object[CAP-1]; // appears too small
res = CANDIDATE.toArray(a);
check(res != a);
check(res[LAST] != null);
// Check equal elements as a.length
a = new Object[CAP]; // appears to match
res = CANDIDATE.toArray(a);
check(res == a);
check(res[last()] != null);
// Check equal elements as a.length
a = new Object[CAP+1]; // appears too big
res = CANDIDATE.toArray(a);
check(res == a);
check(res[last()] == null);
// Check less elements than expected, but more than a.length
a = new Object[CAP-2]; // appears too small
CANDIDATE.setPseudoConcurrentChronologicalSizeSequence(CAP, CAP-1);
res = CANDIDATE.toArray(a);
check(res != a);
check(res.length == CAP-1);
check(res[LAST-1] != null);
// Check less elements than expected, but equal as a.length
a = Arrays.copyOf(OBJECTS, CAP); // appears to match
CANDIDATE.setPseudoConcurrentChronologicalSizeSequence(CAP, CAP-1);
res = CANDIDATE.toArray(a);
check(res == a);
check(res[last()] == null);
// Check more elements than expected and more than a.length
a = new Object[CAP-1]; // appears to match
CANDIDATE.setPseudoConcurrentChronologicalSizeSequence(CAP-1, CAP);
res = CANDIDATE.toArray(a);
check(res != a);
check(res[LAST] != null);
// Check more elements than expected, but equal as a.length
a = new Object[CAP-1]; // appears to match
CANDIDATE.setPseudoConcurrentChronologicalSizeSequence(CAP-2, CAP-1);
res = CANDIDATE.toArray(a);
check(res == a);
check(res[last()] != null);
// Check more elements than expected, but less than a.length
a = Arrays.copyOf(OBJECTS, CAP); // appears to match
CANDIDATE.setPseudoConcurrentChronologicalSizeSequence(CAP-2, CAP-1);
res = CANDIDATE.toArray(a);
check(res == a);
check(res[last()] == null);
test_7121314();
}
/**
* @bug 7121314
* @summary return the original array if the collection concurrently
shrinks and will fit
*/
protected void test_7121314() throws Throwable {
// Check equal elements as a.length, but less than expected
a = new Object[CAP-1]; // appears too small
CANDIDATE.setPseudoConcurrentChronologicalSizeSequence(CAP, CAP-1);
res = CANDIDATE.toArray(a);
check(res == a);
check(res[last()] != null);
// Check less elements than a.length and less than expected
a = Arrays.copyOf(OBJECTS, CAP-1); // appears too small
CANDIDATE.setPseudoConcurrentChronologicalSizeSequence(CAP, CAP-2);
res = CANDIDATE.toArray(a);
check(res == a);
check(res[last()] == null);
}
public static void main(String[] args) throws Throwable {
run(new ToArray());
}
}