Home | History | Annotate | Download | only in lang
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package org.apache.harmony.tests.java.lang;
     19 
     20 import junit.framework.TestCase;
     21 import java.util.concurrent.atomic.AtomicReference;
     22 
     23 public class ThreadLocalTest extends TestCase {
     24 
     25     /**
     26      * java.lang.ThreadLocal#ThreadLocal()
     27      */
     28     public void test_Constructor() {
     29         new ThreadLocal<Object>();
     30     }
     31 
     32     /**
     33      * java.lang.ThreadLocal#remove()
     34      */
     35     public void test_remove() {
     36         ThreadLocal<String> tl = new ThreadLocal<String>() {
     37             @Override
     38             protected String initialValue() {
     39                 return "initial";
     40             }
     41         };
     42 
     43         assertEquals("initial", tl.get());
     44         tl.set("fixture");
     45         assertEquals("fixture", tl.get());
     46         tl.remove();
     47         assertEquals("initial", tl.get());
     48     }
     49 
     50     /**
     51      * java.lang.ThreadLocal#get()
     52      */
     53     public void test_get() {
     54         // Test for method java.lang.Object java.lang.ThreadLocal.get()
     55         ThreadLocal<Object> l = new ThreadLocal<Object>();
     56         assertNull("ThreadLocal's initial value is null", l.get());
     57 
     58         // The ThreadLocal has to run once for each thread that touches the
     59         // ThreadLocal
     60         final Object INITIAL_VALUE = "'foo'";
     61         final ThreadLocal<Object> l1 = new ThreadLocal<Object>() {
     62             @Override
     63             protected Object initialValue() {
     64                 return INITIAL_VALUE;
     65             }
     66         };
     67 
     68         assertTrue("ThreadLocal's initial value should be " + INITIAL_VALUE
     69                 + " but is " + l1.get(), l1.get() == INITIAL_VALUE);
     70 
     71         // We need this because inner types cannot assign to variables in
     72         // container method. But assigning to object slots in the container
     73         // method is ok.
     74         class ResultSlot {
     75             public Object result = null;
     76         }
     77 
     78         final ResultSlot THREADVALUE = new ResultSlot();
     79         Thread t = new Thread() {
     80             @Override
     81             public void run() {
     82                 THREADVALUE.result = l1.get();
     83             }
     84         };
     85 
     86         // Wait for the other Thread assign what it observes as the value of the
     87         // variable
     88         t.start();
     89         try {
     90             t.join();
     91         } catch (InterruptedException ie) {
     92             fail("Interrupted!!");
     93         }
     94 
     95         assertTrue("ThreadLocal's initial value in other Thread should be "
     96                 + INITIAL_VALUE, THREADVALUE.result == INITIAL_VALUE);
     97 
     98         /* Regression test for implementation vulnerability reported
     99          * on Harmony dev list.
    100          */
    101         ThreadLocal<Object> thrVar = new ThreadLocal<Object>() {
    102             public int hashCode() {
    103                 fail("ThreadLocal should not be asked for it's hashCode");
    104                 return 0; // never reached
    105             }
    106         };
    107         thrVar.get();
    108     }
    109 
    110     /**
    111      * java.lang.ThreadLocal#set(java.lang.Object)
    112      */
    113     public void test_setLjava_lang_Object() {
    114         // Test for method void java.lang.ThreadLocal.set(java.lang.Object)
    115 
    116         final Object OBJ = new Object();
    117         final ThreadLocal<Object> l = new ThreadLocal<Object>();
    118         l.set(OBJ);
    119         assertTrue("ThreadLocal's initial value is " + OBJ, l.get() == OBJ);
    120 
    121         // We need this because inner types cannot assign to variables in
    122         // container method.
    123         // But assigning to object slots in the container method is ok.
    124         class ResultSlot {
    125             public Object result = null;
    126         }
    127 
    128         final ResultSlot THREADVALUE = new ResultSlot();
    129         Thread t = new Thread() {
    130             @Override
    131             public void run() {
    132                 THREADVALUE.result = l.get();
    133             }
    134         };
    135 
    136         // Wait for the other Thread assign what it observes as the value of the
    137         // variable
    138         t.start();
    139         try {
    140             t.join();
    141         } catch (InterruptedException ie) {
    142             fail("Interrupted!!");
    143         }
    144 
    145         // ThreadLocal is not inherited, so the other Thread should see it as
    146         // null
    147         assertNull("ThreadLocal's value in other Thread should be null",
    148                 THREADVALUE.result);
    149 
    150     }
    151 
    152     /**
    153      * java.lang.ThreadLocal#withInitial()
    154      */
    155     public void test_withInitial() {
    156         // The ThreadLocal has to run once for each thread that touches the
    157         // ThreadLocal
    158         final String INITIAL_VALUE = "'foo'";
    159         final String OTHER_VALUE = "'bar'";
    160         final ThreadLocal<String> l1 = ThreadLocal.withInitial(() -> INITIAL_VALUE);
    161 
    162         assertSame(INITIAL_VALUE, l1.get());
    163 
    164         l1.set(OTHER_VALUE);
    165         assertSame(OTHER_VALUE, l1.get());
    166 
    167         assertTrue("ThreadLocal's value should be " + OTHER_VALUE
    168                 + " but is " + l1.get(), l1.get() == OTHER_VALUE);
    169 
    170         AtomicReference<String> threadValue = new AtomicReference<String>();
    171 
    172         Thread t = new Thread() {
    173             @Override
    174             public void run() {
    175                 threadValue.set(l1.get());
    176             }
    177         };
    178 
    179         // Wait for the other Thread assign what it observes as the value of the
    180         // variable
    181         t.start();
    182         try {
    183             t.join();
    184         } catch (InterruptedException ie) {
    185             fail("Interrupted!!");
    186         }
    187 
    188         assertSame(INITIAL_VALUE, threadValue.get());
    189     }
    190 }
    191