Request for review : 7121314 : Behavior mismatch between AbstractCollection.toArray(T[] ) and its spec
Ulf Zibis
Ulf.Zibis at gmx.de
Wed Mar 28 18:48:59 UTC 2012
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
>
-------------- next part --------------
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.");
}
};
}
}
-------------- next part --------------
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());
}
}
More information about the core-libs-dev
mailing list