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
18package org.apache.harmony.luni.tests.java.net;
19
20import java.net.InetAddress;
21
22import tests.support.Support_Configuration;
23
24public class InetAddressThreadTest extends junit.framework.TestCase {
25
26    private static boolean someoneDone[] = new boolean[2];
27
28    protected static boolean threadedTestSucceeded;
29
30    protected static String threadedTestErrorString;
31
32    /**
33     * This class is used to test inet_ntoa, gethostbyaddr and gethostbyname
34     * functions in the VM to make sure they're threadsafe. getByName will cause
35     * the gethostbyname function to be called. getHostName will cause the
36     * gethostbyaddr to be called. getHostAddress will cause inet_ntoa to be
37     * called.
38     */
39    static class threadsafeTestThread extends Thread {
40        private String lookupName;
41
42        private InetAddress testAddress;
43
44        private int testType;
45
46        /*
47         * REP_NUM can be adjusted if desired. Since this error is
48         * non-deterministic it may not always occur. Setting REP_NUM higher,
49         * increases the chances of an error being detected, but causes the test
50         * to take longer. Because the Java threads spend a lot of time
51         * performing operations other than running the native code that may not
52         * be threadsafe, it is quite likely that several thousand iterations
53         * will elapse before the first error is detected.
54         */
55        private static final int REP_NUM = 20000;
56
57        public threadsafeTestThread(String name, String lookupName,
58                InetAddress testAddress, int type) {
59            super(name);
60            this.lookupName = lookupName;
61            this.testAddress = testAddress;
62            testType = type;
63        }
64
65        public void run() {
66            try {
67                String correctName = testAddress.getHostName();
68                String correctAddress = testAddress.getHostAddress();
69                long startTime = System.currentTimeMillis();
70
71                synchronized (someoneDone) {
72                }
73
74                for (int i = 0; i < REP_NUM; i++) {
75                    if (someoneDone[testType]) {
76                        break;
77                    } else if ((i % 25) == 0
78                            && System.currentTimeMillis() - startTime > 240000) {
79                        System.out
80                                .println("Exiting due to time limitation after "
81                                        + i + " iterations");
82                        break;
83                    }
84
85                    InetAddress ia = InetAddress.getByName(lookupName);
86                    String hostName = ia.getHostName();
87                    String hostAddress = ia.getHostAddress();
88
89                    // Intentionally not looking for exact name match so that
90                    // the test works across different platforms that may or
91                    // may not include a domain suffix on the hostname
92                    if (!hostName.startsWith(correctName)) {
93                        threadedTestSucceeded = false;
94                        threadedTestErrorString = (testType == 0 ? "gethostbyname"
95                                : "gethostbyaddr")
96                                + ": getHostName() returned "
97                                + hostName
98                                + " instead of " + correctName;
99                        break;
100                    }
101                    // IP addresses should match exactly
102                    if (!correctAddress.equals(hostAddress)) {
103                        threadedTestSucceeded = false;
104                        threadedTestErrorString = (testType == 0 ? "gethostbyname"
105                                : "gethostbyaddr")
106                                + ": getHostName() returned "
107                                + hostAddress
108                                + " instead of " + correctAddress;
109                        break;
110                    }
111
112                }
113                someoneDone[testType] = true;
114            } catch (Exception e) {
115                threadedTestSucceeded = false;
116                threadedTestErrorString = e.toString();
117            }
118        }
119    }
120
121    /**
122     * @tests java.net.InetAddress#getHostName()
123     */
124    public void test_getHostName() throws Exception {
125        // Test for method java.lang.String java.net.InetAddress.getHostName()
126
127        // Make sure there is no caching
128        String originalPropertyValue = System
129                .getProperty("networkaddress.cache.ttl");
130        System.setProperty("networkaddress.cache.ttl", "0");
131
132        // Test for threadsafety
133        try {
134            InetAddress lookup1 = InetAddress.getByName("localhost");
135            assertEquals("127.0.0.1", lookup1.getHostAddress());
136            InetAddress lookup2 = InetAddress.getByName("localhost");
137            assertEquals("127.0.0.1", lookup2.getHostAddress());
138            threadsafeTestThread thread1 = new threadsafeTestThread("1",
139                    lookup1.getHostName(), lookup1, 0);
140            threadsafeTestThread thread2 = new threadsafeTestThread("2",
141                    lookup2.getHostName(), lookup2, 0);
142            threadsafeTestThread thread3 = new threadsafeTestThread("3",
143                    lookup1.getHostAddress(), lookup1, 1);
144            threadsafeTestThread thread4 = new threadsafeTestThread("4",
145                    lookup2.getHostAddress(), lookup2, 1);
146
147            // initialize the flags
148            threadedTestSucceeded = true;
149            synchronized (someoneDone) {
150                thread1.start();
151                thread2.start();
152                thread3.start();
153                thread4.start();
154            }
155            thread1.join();
156            thread2.join();
157            thread3.join();
158            thread4.join();
159            /* FIXME: comment the assertion below because it is platform/configuration dependent
160             * Please refer to HARMONY-1664 (https://issues.apache.org/jira/browse/HARMONY-1664)
161             * for details
162             */
163//            assertTrue(threadedTestErrorString, threadedTestSucceeded);
164        } finally {
165            // restore the old value of the property
166            if (originalPropertyValue == null)
167                // setting the property to -1 has the same effect as having the
168                // property be null
169                System.setProperty("networkaddress.cache.ttl", "-1");
170            else
171                System.setProperty("networkaddress.cache.ttl",
172                        originalPropertyValue);
173        }
174    }
175}
176