1/*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/publicdomain/zero/1.0/
5 * Other contributors include Andrew Wright, Jeffrey Hayes,
6 * Pat Fisher, Mike Judd.
7 */
8
9package jsr166;
10
11import junit.framework.Test;
12import junit.framework.TestSuite;
13
14public class ThreadLocalTest extends JSR166TestCase {
15    // android-note: Removed because the CTS runner does a bad job of
16    // retrying tests that have suite() declarations.
17    //
18    // public static void main(String[] args) {
19    //     main(suite(), args);
20    // }
21    // public static Test suite() {
22    //     return new TestSuite(ThreadLocalTest.class);
23    // }
24
25    static ThreadLocal<Integer> tl = new ThreadLocal<Integer>() {
26            public Integer initialValue() {
27                return one;
28            }
29        };
30
31    static InheritableThreadLocal<Integer> itl =
32        new InheritableThreadLocal<Integer>() {
33            protected Integer initialValue() {
34                return zero;
35            }
36
37            protected Integer childValue(Integer parentValue) {
38                return new Integer(parentValue.intValue() + 1);
39            }
40        };
41
42    /**
43     * remove causes next access to return initial value
44     */
45    public void testRemove() {
46        assertSame(tl.get(), one);
47        tl.set(two);
48        assertSame(tl.get(), two);
49        tl.remove();
50        assertSame(tl.get(), one);
51    }
52
53    /**
54     * remove in InheritableThreadLocal causes next access to return
55     * initial value
56     */
57    public void testRemoveITL() {
58        assertSame(itl.get(), zero);
59        itl.set(two);
60        assertSame(itl.get(), two);
61        itl.remove();
62        assertSame(itl.get(), zero);
63    }
64
65    private class ITLThread extends Thread {
66        final int[] x;
67        ITLThread(int[] array) { x = array; }
68        public void run() {
69            Thread child = null;
70            if (itl.get().intValue() < x.length - 1) {
71                child = new ITLThread(x);
72                child.start();
73            }
74            Thread.yield();
75
76            int threadId = itl.get().intValue();
77            for (int j = 0; j < threadId; j++) {
78                x[threadId]++;
79                Thread.yield();
80            }
81
82            if (child != null) { // Wait for child (if any)
83                try {
84                    child.join();
85                } catch (InterruptedException e) {
86                    threadUnexpectedException(e);
87                }
88            }
89        }
90    }
91
92    /**
93     * InheritableThreadLocal propagates generic values.
94     */
95    public void testGenericITL() throws InterruptedException {
96        final int threadCount = 10;
97        final int[] x = new int[threadCount];
98        Thread progenitor = new ITLThread(x);
99        progenitor.start();
100        progenitor.join();
101        for (int i = 0; i < threadCount; i++) {
102            assertEquals(i, x[i]);
103        }
104    }
105}
106