/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.harmony.tests.java.lang;
import junit.framework.TestCase;
public class ThreadLocalTest extends TestCase {
/**
* java.lang.ThreadLocal#ThreadLocal()
*/
public void test_Constructor() {
new ThreadLocal<Object>();
}
/**
* java.lang.ThreadLocal#remove()
*/
public void test_remove() {
ThreadLocal<String> tl = new ThreadLocal<String>() {
@Override
protected String initialValue() {
return "initial";
}
};
assertEquals("initial", tl.get());
tl.set("fixture");
assertEquals("fixture", tl.get());
tl.remove();
assertEquals("initial", tl.get());
}
/**
* java.lang.ThreadLocal#get()
*/
public void test_get() {
// Test for method java.lang.Object java.lang.ThreadLocal.get()
ThreadLocal<Object> l = new ThreadLocal<Object>();
assertNull("ThreadLocal's initial value is null", l.get());
// The ThreadLocal has to run once for each thread that touches the
// ThreadLocal
final Object INITIAL_VALUE = "'foo'";
final ThreadLocal<Object> l1 = new ThreadLocal<Object>() {
@Override
protected Object initialValue() {
return INITIAL_VALUE;
}
};
assertTrue("ThreadLocal's initial value should be " + INITIAL_VALUE
+ " but is " + l1.get(), l1.get() == INITIAL_VALUE);
// We need this because inner types cannot assign to variables in
// container method. But assigning to object slots in the container
// method is ok.
class ResultSlot {
public Object result = null;
}
final ResultSlot THREADVALUE = new ResultSlot();
Thread t = new Thread() {
@Override
public void run() {
THREADVALUE.result = l1.get();
}
};
// Wait for the other Thread assign what it observes as the value of the
// variable
t.start();
try {
t.join();
} catch (InterruptedException ie) {
fail("Interrupted!!");
}
assertTrue("ThreadLocal's initial value in other Thread should be "
+ INITIAL_VALUE, THREADVALUE.result == INITIAL_VALUE);
/* Regression test for implementation vulnerability reported
* on Harmony dev list.
*/
ThreadLocal<Object> thrVar = new ThreadLocal<Object>() {
public int hashCode() {
fail("ThreadLocal should not be asked for it's hashCode");
return 0; // never reached
}
};
thrVar.get();
}
/**
* java.lang.ThreadLocal#set(java.lang.Object)
*/
public void test_setLjava_lang_Object() {
// Test for method void java.lang.ThreadLocal.set(java.lang.Object)
final Object OBJ = new Object();
final ThreadLocal<Object> l = new ThreadLocal<Object>();
l.set(OBJ);
assertTrue("ThreadLocal's initial value is " + OBJ, l.get() == OBJ);
// We need this because inner types cannot assign to variables in
// container method.
// But assigning to object slots in the container method is ok.
class ResultSlot {
public Object result = null;
}
final ResultSlot THREADVALUE = new ResultSlot();
Thread t = new Thread() {
@Override
public void run() {
THREADVALUE.result = l.get();
}
};
// Wait for the other Thread assign what it observes as the value of the
// variable
t.start();
try {
t.join();
} catch (InterruptedException ie) {
fail("Interrupted!!");
}
// ThreadLocal is not inherited, so the other Thread should see it as
// null
assertNull("ThreadLocal's value in other Thread should be null",
THREADVALUE.result);
}
}