//
// Copyright (C) 2010 United States Government as represented by the
// Administrator of the National Aeronautics and Space Administration
// (NASA). All Rights Reserved.
//
// This software is distributed under the NASA Open Source Agreement
// (NOSA), version 1.3. The NOSA has been approved by the Open Source
// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
// directory tree for the complete NOSA document.
//
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
//
package gov.nasa.jpf.util;
import static gov.nasa.jpf.util.SparseClusterArray.S1;
import java.util.HashMap;
import java.util.Random;
import org.junit.Test;
import gov.nasa.jpf.util.SparseClusterArray.Entry;
import gov.nasa.jpf.util.SparseClusterArray.Snapshot;
import gov.nasa.jpf.util.test.TestJPF;
/**
* unit test for gov.nasa.jpf.util.SparseClusterArray
*/
@SuppressWarnings({ "unused" })
public class SparseClusterArrayTest extends TestJPF {
public static void main (String[] args){
// our performance evals
if (args.length == 1){
String mthName = args[0];
if (mthName.equals("evalHashMap")){
evalHashMap();
return;
} else if (mthName.equals("evalSparseClusterArray")){
evalSparseClusterArray();
return;
}
}
// the regression tests
runTestsOfThisClass(args);
}
@Test
public void testBasic() {
SparseClusterArray<Object> arr = new SparseClusterArray<Object>();
Object v;
int ref;
ref = (1 << S1) | 42;
arr.set(ref, (v = new Integer(ref)));
Object o = arr.get(ref);
System.out.println(o);
assert o.equals(v);
ref = (2 << S1);
arr.set(ref, new Integer(ref));
System.out.println("cardinality = " + arr.cardinality());
assert arr.cardinality() == 2;
for (Object e : arr) {
System.out.println(e);
}
}
@Test
public void testNextNull () {
Object e = new Integer(42);
SparseClusterArray<Object> arr = new SparseClusterArray<Object>();
int k;
int limit = 10000000;
arr.set(0, e);
k = arr.firstNullIndex(0, limit);
System.out.println("k=" + k); // 1
assert k == 1;
arr.set(0,null);
k = arr.firstNullIndex(0, limit);
System.out.println("k=" + k); // 0
assert k == 0;
arr.set(511, 511);
int i=0;
for (;i<512; i++) {
arr.set(i, e);
}
System.out.println(arr.get(511));
System.out.println(arr.get(512));
k = arr.firstNullIndex(0, limit);
assert k == 512;
long t1 = System.currentTimeMillis();
for (int j=0; j<100000; j++) {
k = arr.firstNullIndex(0, limit);
}
long t2 = System.currentTimeMillis();
System.out.println("k=" + k + ", 100000 lookups in: " + (t2 - t1)); // 512
for (;i<2048;i++) {
arr.set(i, e);
}
k = arr.firstNullIndex(0, limit);
System.out.println("k=" + k); // 2048 (no chunk)
assert k == 2048;
k = arr.firstNullIndex(0, 2048);
System.out.println("k=" + k); // -1
assert k == -1;
arr.set(2048, e);
arr.set(2048,null);
k = arr.firstNullIndex(0, limit);
System.out.println("k=" + k); // 2048 (new chunk)
assert k == 2048;
for (; i<2500; i++) {
arr.set(i, e);
}
k = arr.firstNullIndex(0, limit);
System.out.println("k=" + k); // 2500
assert k == 2500;
}
@Test
public void testClusterNextNull () {
SparseClusterArray<Integer> arr = new SparseClusterArray<Integer>();
arr.set(0, 0); // have a lower chunk
int tid = 2;
int base = (tid << SparseClusterArray.S1);
int r = arr.firstNullIndex(base, SparseClusterArray.MAX_CLUSTER_ENTRIES);
assert r == 0x02000000;
System.out.println(Integer.toHexString(r));
arr.set(r, 42);
r = arr.firstNullIndex(base, SparseClusterArray.MAX_CLUSTER_ENTRIES);
assert r == 0x02000001;
System.out.println(Integer.toHexString(r));
for (int i=r; i < 0x0200ffff; i++){
arr.set(i,42);
}
arr.set(0x200f0ff, null);
r = arr.firstNullIndex(base, SparseClusterArray.MAX_CLUSTER_ENTRIES);
assert r == 0x200f0ff;
System.out.println(Integer.toHexString(r));
arr.set(0x200f0ff, 42);
r = arr.firstNullIndex(base, SparseClusterArray.MAX_CLUSTER_ENTRIES);
assert r == 0x200ffff;
System.out.println(Integer.toHexString(r));
}
@Test
public void testClone() {
SparseClusterArray<Integer> arr = new SparseClusterArray<Integer>();
arr.set(0, new Integer(0));
arr.set(42, new Integer(42));
arr.set(6762, new Integer(6762));
arr.set(6762, null);
Cloner<Integer> cloner = new Cloner<Integer>() {
public Integer clone (Integer other) {
return new Integer(other);
}
};
SparseClusterArray<Integer> newArr = arr.deepCopy(cloner);
for (Integer i : newArr) {
System.out.println(i);
}
assert newArr.cardinality() == 2;
assert newArr.get(0) == 0;
assert newArr.get(42) == 42;
assert newArr.get(6762) == null;
}
@Test
public void testSnapshot() {
SparseClusterArray<Integer> arr = new SparseClusterArray<Integer>();
arr.set(0, new Integer(0));
arr.set(42, new Integer(42));
arr.set(4095, new Integer(4095));
arr.set(4096, new Integer(4096));
arr.set(7777, new Integer(7777));
arr.set(67620, new Integer(67620));
arr.set(67620, null);
arr.set(7162827, new Integer(7162827));
Transformer<Integer,String> i2s = new Transformer<Integer,String>() {
public String transform (Integer n) {
return n.toString();
}
};
Transformer<String,Integer> s2i = new Transformer<String,Integer>() {
public Integer transform (String s) {
return new Integer( Integer.parseInt(s));
}
};
Snapshot<Integer,String> snap = arr.getSnapshot(i2s);
// just for debugging purposes
int len = snap.size();
for (int i=0; i<len; i++){
System.out.println("a[" + snap.getIndex(i) + "] = " + snap.getValue(i));
}
arr.set(42,null);
arr.set(87, new Integer(87));
arr.set(7162827, new Integer(-1));
arr.restore(snap, s2i);
for (Integer i : arr) {
System.out.println(i);
}
assert arr.cardinality() == 6;
assert arr.get(0) == 0;
assert arr.get(42) == 42;
assert arr.get(4095) == 4095;
assert arr.get(4096) == 4096;
assert arr.get(7777) == 7777;
assert arr.get(7162827) == 7162827;
}
@Test
public void testChanges() {
SparseClusterArray<Integer> arr = new SparseClusterArray<Integer>();
arr.set(42, new Integer(42));
arr.set(6276, new Integer(6276));
arr.trackChanges();
arr.set(0, new Integer(0));
arr.set(42, new Integer(-1));
arr.set(4095, new Integer(4095));
arr.set(4096, new Integer(4096));
arr.set(7777, new Integer(7777));
arr.set(7162827, new Integer(7162827));
Entry<Integer> changes = arr.getChanges();
arr.revertChanges(changes);
for (Integer i : arr) {
System.out.println(i);
}
assert arr.cardinality() == 2;
assert arr.get(42) == 42;
assert arr.get(6276) == 6276;
}
@Test
public void testIterator() {
SparseClusterArray<Integer> arr = new SparseClusterArray<Integer>();
for (int i=0; i<300; i++){
arr.set(i,i);
}
for (int i=700; i < 1000; i++){
arr.set(i,i);
}
// remove some while we iterate
boolean lastSeen = false;
int n = 0;
for (Integer i : arr){
if (i == 200){
for (int j = 150; j<750; j++){
arr.set(j, null);
}
} else if (i == 999){
lastSeen = true;
}
n++;
}
assert n == 451 : "wrong number of visited elements: " + n; // [0-200] + [750-999]
assert lastSeen : "last element not seen";
}
@Test
public void testIndexIterator() {
SparseClusterArray<Integer> arr = new SparseClusterArray<Integer>();
for (int i=0; i<300; i++){
arr.set(i,i);
}
for (int i=700; i < 1000; i++){
arr.set(i,i);
}
// remove some while we iterate
boolean lastSeen = false;
int n = 0;
IndexIterator it = arr.getElementIndexIterator(100);
for (int i=it.next(); i>= 0; i = it.next()){
System.out.println(i);
if (i == 200){
for (int j = 150; j<750; j++){
arr.set(j, null);
}
} else if (i == 999){
lastSeen = true;
}
n++;
}
assert n == 351 : "wrong number of visited elements: " + n; // [100-200] + [750-999]
assert lastSeen : "last element not seen";
}
//--- the performance sectopm
final static int MAX_ROUNDS = 1000;
final static int MAX_N = 10000;
final static int MAX_T = 8;
static void evalSparseClusterArray() {
Random random = new Random(0);
Object elem = new Object();
long t1, t2;
int n = 0;
t1 = System.currentTimeMillis();
SparseClusterArray<Object> arr = new SparseClusterArray<Object>();
for (int i=0; i<MAX_ROUNDS; i++) {
int seg = random.nextInt(MAX_T) << S1;
for (int j=0; j<MAX_N; j++) {
int ref = seg | random.nextInt(MAX_N);
//ref |= j;
arr.set(ref, elem);
if (arr.get(ref) == null) throw new RuntimeException("element not set: " + i);
}
}
t2 = System.currentTimeMillis();
System.out.println("SparseArray random write/read of " + arr.cardinality() + " elements: "+ (t2 - t1));
n=0;
t1 = System.currentTimeMillis();
for (Object e : arr) {
n++;
}
t2 = System.currentTimeMillis();
System.out.println("SparseArray iteration over " + n + " elements: " + (t2 - t1));
}
static void evalHashMap() {
Random random = new Random(0);
Object elem = new Object();
long t1, t2;
t1 = System.currentTimeMillis();
HashMap<Integer,Object> arr = new HashMap<Integer,Object>();
for (int i=0; i<MAX_ROUNDS; i++) {
int seg = random.nextInt(MAX_T) << S1;
for (int j=0; j<MAX_N; j++) {
int ref = seg | random.nextInt(MAX_N);
//ref |= j;
arr.put(ref, elem);
if (arr.get(ref) == null) throw new RuntimeException("element not set: " + i);
}
}
t2 = System.currentTimeMillis();
System.out.println("HashMap random write/read of " + arr.size() + " elements: " + (t2 - t1));
int n=0;
t1 = System.currentTimeMillis();
for (Object e : arr.values()) {
n++;
}
t2 = System.currentTimeMillis();
System.out.println("HashMap iteration over " + n + " elements: " + (t2 - t1));
}
}