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.net;
19 
20 import java.net.InetAddress;
21 
22 import tests.support.Support_Configuration;
23 
24 public 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 
threadsafeTestThread(String name, String lookupName, InetAddress testAddress, int type)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 
run()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      * java.net.InetAddress#getHostName()
123      */
test_getHostName()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